PHP - RSS builder - php

I have a old website that generate its own RSS everytime a new post is created. Everything worked when I was on a server with PHP 4 but now that the host change to PHP 5, I always have a "bad formed XML". I was using xml_parser_create() and xml_parse(...) and fwrite(..) to save everything.
Here is the example when saving (I read before save to append old RSS line of course).
function SaveXml()
{
if (!is_file($this->getFileName()))
{
//Création du fichier
$file_handler = fopen($this->getFileName(),"w");
fwrite($file_handler,"");
fclose($file_handler);
}//Fin du if
//Header xml version="1.0" encoding="utf-8"
$strFileData = '<?xml version="1.0" encoding="iso-8859-1" ?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>'.$this->getProjectName().'</title><link>http://www.mywebsite.com</link><description>My description</description><lastBuildDate>' . date("r"). '</lastBuildDate>';
//Data
reset($this->arrData);
foreach($this->arrData as $i => $value)
{
$strFileData .= '<item>';
$strFileData .= '<title>'. $this->GetNews($i,0) . '</title>';
$strFileData .= '<pubDate>'. $this->GetNews($i,1) . '</pubDate>';
$strFileData .= '<dc:creator>'. $this->GetNews($i,2) . '</dc:creator>';
$strFileData .= '<description><![CDATA['. $this->GetNews($i,3) . ']]> </description>';
$strFileData .= '<link><![CDATA['. $this->GetNews($i,4) . ']]></link>';
$strFileData .= '<guid>'. $this->GetNews($i,4) . '</guid>';
//$strFileData .= '<category>'. $this->GetNews($i,5) . '</category>';
$strFileData .= '<category>Mycategory</category>';
$strFileData .= '</item>';
}//Fin du for i
$strFileData .= '</channel></rss>';
if (file_exists($this->getFileName()))//Détruit le fichier
unlink($this->getFileName());
$file_handler = fopen($this->getFileName(),"w");
fwrite($file_handler,$strFileData);
fclose($file_handler);
}//Fin de SaveXml
My question is : how do you create and fill up your RSS in PHP?

At swcombine.com we use Feedcreator. Use that one and your problem will be gone. :)
Here is the PHP code to use it once installed:
function feed_simnews() {
$objRSS = new UniversalFeedCreator();
$objRSS->title = 'My News';
$objRSS->link = 'http://link.to/news.php';
$objRSS->description = 'daily news from me';
$objRSS->xsl = 'http://link.to/feeds/feedxsl.xsl';
$objRSS->language = 'en';
$objRSS->copyright = 'Copyright: Mine!';
$objRSS->webmaster = 'webmaster#somewhere.com';
$objRSS->syndicationURL = 'http://link.to/news/simnews.php';
$objRSS->ttl = 180;
$objImage = new FeedImage();
$objImage->title = 'my logo';
$objImage->url = 'http://link.to/feeds/logo.jpg';
$objImage->link = 'http://link.to';
$objImage->description = 'Feed provided by link.to. Click to visit.';
$objImage->width = 120;
$objImage->height = 60;
$objRSS->image = $objImage;
//Function retrieving an array of your news from date start to last week
$colNews = getYourNews(array('start_date' => 'Last week'));
foreach($colNews as $p) {
$objItem = new FeedItem();
$objItem->title = $p->title;
$objItem->description = $p->body;
$objItem->link = $p->link;
$objItem->date = $p->date;
$objItem->author = $p->author;
$objItem->guid = $p->guid;
$objRSS->addItem($objItem);
}
$objRSS->saveFeed('RSS2.0', 'http://link.to/feeds/news.xml', false);
};
Quite KISS. :)

I would use simpleXML to create the required structure and export the XML. Then I'd cache it to disk with file_put_contents().

I've used this LGPL-licensed feedcreator class in the past and it worked quite well for the very simple use I had for it.

Not a full answer, but you don't have to parse your own XML. It will hurt performance and reliability.
But definitely make sure it is well-formed. It shouldn't be very hard if you generate it by hand or using general-purpose tools. Or maybe your included HTML ruins it?

There are lots of things that can make XML malformed. It might be a problem with character entities (a '<', '>', or '&' in the data between the XML tags). Try running anything output from a database through htmlentities() when you concatenate the string. Do you have an example of the generated XML for us to look at so we can see where the problem is?

PHP5 now comes with the SimpleXML extension, it's a pretty quick way to build valid XML if your needs aren't complicated.
However, the problem you're suggesting doesn't seem to an issue of implementation more a problem of syntax. Perhaps you could update your question with a code example, or, a copy of the XML that is produced.

Related

PHP eBay GetOrders API (Unable To fetch Any Data)

I am Trying to fetch ebay orders by using getOrders API, when i execute ebay PHP SDK it print:
"Sorry No entries found in the Time period requested. Change CreateTimeFrom/CreateTimeTo and Try again"
Please Help me...
Official ebay PHP SDK code :
<?php
/* © 2013 eBay Inc., All Rights Reserved */
/* Licensed under CDDL 1.0 - http://opensource.org/licenses/cddl1.php */
?>
<?php require_once('get-common/keys.php') ; //include keys file for auth token and other credentials ?>
<?php require_once('get-common/eBaySession.php') ; //include session file for curl operations ?>
<?php
//SiteID must also be set in the Request's XML
//SiteID = 0 (US) - UK = 3, Canada = 2, Australia = 15, ....
//SiteID Indicates the eBay site to associate the call with
$siteID = 0;
//the call being made:
$verb = 'GetOrders';
//Time with respect to GMT
//by default retreive orders in last 30 minutes
$CreateTimeFrom = gmdate("Y-m-d\TH:i:s",time()-(2*40*24*60*60)); //current time minus 80 Days
//echo "</br>";
$CreateTimeTo = gmdate("Y-m-d\TH:i:s");
//If you want to hard code From and To timings, Follow the below format in "GMT".
//$CreateTimeFrom = YYYY-MM-DDTHH:MM:SS; //GMT
//$CreateTimeTo = YYYY-MM-DDTHH:MM:SS; //GMT
///Build the request Xml string
$requestXmlBody = '<?xml version="1.0" encoding="utf-8" ?>';
$requestXmlBody .= '<GetOrdersRequest xmlns="urn:ebay:apis:eBLBaseComponents">';
$requestXmlBody .= '<DetailLevel>ReturnAll</DetailLevel>';
$requestXmlBody .= "<CreateTimeFrom>".$CreateTimeFrom."</CreateTimeFrom><CreateTimeTo>".$CreateTimeTo."</CreateTimeTo>";
$requestXmlBody .= '<OrderRole>Seller</OrderRole><OrderStatus>All</OrderStatus>';
$requestXmlBody .= "<RequesterCredentials><eBayAuthToken>$userToken</eBayAuthToken></RequesterCredentials>";
$requestXmlBody.="<WarningLevel>High</WarningLevel>";
$requestXmlBody .= '</GetOrdersRequest>';
//Create a new eBay session with all details pulled in from included keys.php
$session = new eBaySession($userToken, $devID, $appID, $certID, $serverUrl, $compatabilityLevel, $siteID, $verb);
//send the request and get response
$responseXml = $session->sendHttpRequest($requestXmlBody);
if (stristr($responseXml, 'HTTP 404') || $responseXml == '')
die('<P>Error sending request');
//echo "<pre>";
//var_dump($responseXml);
//die;
//Xml string is parsed and creates a DOM Document object
$responseDoc = new DomDocument();
$responseDoc->loadXML($responseXml);
//get any error nodes
$errors = $responseDoc->getElementsByTagName('Errors');
$response = simplexml_import_dom($responseDoc);
$entries = $response->PaginationResult->TotalNumberOfEntries;
//if there are error nodes
if ($errors->length > 0) {
echo '<P><B>eBay returned the following error(s):</B>';
//display each error
//Get error code, ShortMesaage and LongMessage
$code = $errors->item(0)->getElementsByTagName('ErrorCode');
$shortMsg = $errors->item(0)->getElementsByTagName('ShortMessage');
$longMsg = $errors->item(0)->getElementsByTagName('LongMessage');
//Display code and shortmessage
echo '<P>', $code->item(0)->nodeValue, ' : ', str_replace(">", ">", str_replace("<", "<", $shortMsg->item(0)->nodeValue));
//if there is a long message (ie ErrorLevel=1), display it
if (count($longMsg) > 0)
echo '<BR>', str_replace(">", ">", str_replace("<", "<", $longMsg->item(0)->nodeValue));
}else { //If there are no errors, continue
if(isset($_GET['debug']))
{
header("Content-type: text/xml");
print_r($responseXml);
}else
{ //$responseXml is parsed in view.php
include_once 'view.php';
}
}
?>
I would recommend the ebay-sdk-php from devbay.net :
https://github.com/davidtsadler/ebay-sdk-php
https://github.com/davidtsadler/ebay-sdk-examples
As for the date, I could be wrong, but I think it requires DateTime. Something like
CreateTimeFrom = new DateTime('02-10-2016');
CreateTimeTo = new DateTime('02-11-2016');
But I think you will have an easier time with the ebay-sdk-php
edit:
Actually I've been messing around with this more lately.
The default works for me
$CreateTimeFrom = gmdate("Y-m-d\TH:i:s",time()-1800); //current time minus 30 minutes
$CreateTimeTo = gmdate("Y-m-d\TH:i:s");
or you can hardcode your range like the following:
//If you want to hard code From and To timings, Follow the below format in "GMT".
//$CreateTimeFrom = YYYY-MM-DDTHH:MM:SS; //GMT
//$CreateTimeTo = YYYY-MM-DDTHH:MM:SS; //GMT
such as the following:
$CreateTimeFrom = '2017-03-20T00:00:00Z'; //GMT
$CreateTimeTo = '2017-03-22T00:00:00Z'; //GMT
Alternatively, you can just simply not use CreatedTimeTo and CreatedTimeFrom and use NumberOfDays instead
which is basically just commenting out CreatedTimeTo and CreatedTimeFrom
//$requestXmlBody .= "<CreateTimeFrom>$CreateTimeFrom</CreateTimeFrom><CreateTimeTo>$CreateTimeTo</CreateTimeTo>";
and directly underneath it use NumberOfDays
$requestXmlBody .= "<NumberOfDays>2</NumberOfDays>";

How to get eBay item URL based on item ID

I would like to get the item URL based on the item ID. After searching, I found that I can use GetSingleItem to achieve my goal. However, I got an error:
eBay returned the following error(s):
2 : Unsupported API call.
The API call "GetSingleItem" is invalid or not supported in this release.
Here is my code (all configuration are correct because I can use GetOrders by using these configs):
$subverb = "GetSingleItem";
$requestXmlBody = '<?xml version="1.0" encoding="utf-8" ?>';
$requestXmlBody .= '<GetSingleItemRequest xmlns="urn:ebay:apis:eBLBaseComponents">';
$requestXmlBody .= "<ItemID>111986554711</ItemID>";
$requestXmlBody .= '</GetSingleItemRequest>';
//Create a new eBay session with all details pulled in from included keys.php
$session = new eBaySession($userToken, $devID, $appID, $certID, $serverUrl, $compatabilityLevel, $siteID, $subverb);
//send the request and get response
$responseXml = $session->sendHttpRequest($requestXmlBody);
if (stristr($responseXml, 'HTTP 404') || $responseXml == '')
die('<P>Error sending request');
//Xml string is parsed and creates a DOM Document object
$responseDoc = new DomDocument();
$responseDoc->loadXML($responseXml);
//get any error nodes
$errors = $responseDoc->getElementsByTagName('Errors');
$response = simplexml_import_dom($responseDoc);
$entries = $response->PaginationResult->TotalNumberOfEntries;
//if there are error nodes
if ($errors->length > 0) {
echo '<P><B>eBay returned the following error(s):</B>';
//display each error
//Get error code, ShortMesaage and LongMessage
$code = $errors->item(0)->getElementsByTagName('ErrorCode');
$shortMsg = $errors->item(0)->getElementsByTagName('ShortMessage');
$longMsg = $errors->item(0)->getElementsByTagName('LongMessage');
//Display code and shortmessage
echo '<P>', $code->item(0)->nodeValue, ' : ', str_replace(">", ">", str_replace("<", "<", $shortMsg->item(0)->nodeValue));
//if there is a long message (ie ErrorLevel=1), display it
if (count($longMsg) > 0)
echo '<BR>', str_replace(">", ">", str_replace("<", "<", $longMsg->item(0)->nodeValue));
} else { //If there are no errors, continue
if (isset($_GET['debug'])) {
header("Content-type: text/xml");
print_r($responseXml);
} else {
print("\n; 111986554711: " . $response->Item->ViewItemURLForNaturalSearch);
}
}
Any suggestion? Thank you .
As you discovered, you don't need the API to construct a simple eBay view item landing page URL.
The URL format you discovered works, but it's very old and might not be supported in full or for much longer.
Here's a simple URL format that is pretty current that you can use:
http://www.ebay.com/itm/122225724269
I got an answer without using api. Here is the answer: after I got item ID, I can use "http://cgi.ebay.com/ws/eBayISAPI.dll?ViewItem&item=".$item_id to show my product on ebay.
I found this uri by using GetOrders API.
OrderArray.Order .TransactionArray.Transaction .Variation .VariationViewItemURL
Tip: "not optimized for natural search"
If anyone has any idea about "GetSingleItem", I am willing to know why my code doesn't work.

Namespace in MRSS feed using simplexml PHP Script

Tried to research what I'm doing wrong here, but no luck so far. I want to pull the links and URLs in this MRSS feed using this script, but it's not working. Thought all I needed to do was use namespaces to get the child elements out, but no luck:
<?php
$html = "";
$url = "http://feeds.nascar.com/feeds/video?command=search_videos&media_delivery=http&custom_fields=adtitle%2cfranchise&page_size=100&sort_by=PUBLISH_DATE:DESC&token=217e0d96-bd4a-4451-88ec-404debfaf425&any=franchise:%20Preview%20Show&any=franchise:%20Weekend%20Top%205&any=franchise:Up%20to%20Speed&any=franchise:Press%20Pass&any=franchise:Sprint%20Cup%20Practice%20Clips&any=franchise:Sprint%20Cup%20Highlights&any=franchise:Sprint%20Cup%20Final%20Laps&any=franchise:Sprint%20Cup%20Victory%20Lane&any=franchise:Sprint%20Cup%20Post%20Race%20Reactions&any=franchise:All%20Access&any=franchise:Nationwide%20Series%20Qualifying%20Clips&any=franchise:Nationwide%20Series%20Highlights&any=franchise:Nationwide%20Series%20Final%20Laps&any=franchise:Nationwide%20Series%20Victory%20Lane&any=franchise:Nationwide%20Series%20Post%20Race%20Reactions&any=franchise:Truck%20Series%20Qualifying%20Clips&any=franchise:Truck%20Series%20Highlights&any=franchise:Truck%20Series%20Final%20Laps&any=franchise:Truck%20Series%20Victory%20Lane&any=franchise:Truck%20Series%20Post%20Race%20Reactions&output=mrss";
$xml = simplexml_load_file($url);
$namespaces = $xml->getNamespaces(true); // get namespaces
for($i = 0; $i < 50; $i++){ // will return the 50 most recent videos
$title = $xml->channel->item[$i]->title;
$link = $xml->channel->item[$i]->link;
$pubDate = $xml->channel->item[$i]->pubDate;
$description = $xml->channel->item[$i]->description;
$titleid = $xml->channel->item[$i]->children($namespaces['bc'])->titleid;
$url = $xml->channel->item[$i]->children($namespaces['media'])->url;
$html .= "<h3>$title</h3>$description<p>$pubDate<p>$link<p>Video ID: $titleid<p>
<iframe width='480' height='270' src='http://link.brightcove.com/services/player/bcpid3742068445001?bckey=//my API token goes here &bctid=$titleid&autoStart=false' frameborder='0'></iframe><hr/>";/* this embed code is from the youtube iframe embed code format but is actually using the embedded Ooyala player embedded on the Campus Insiders page. I replaced any specific guid (aka video ID) numbers with the "$guid" variable while keeping the Campus Insider Ooyala publisher ID, "eb3......fad" */
}
echo $html;
?>
I take it this isn't the right approach:
$url = $xml->channel->item[$i]->children($namespaces['media'])->url;
What am I doing wrong here?
Thanks for any and all help!
MD
SimpleXML is deceptively named as it is more difficult to use than DOMDocument or the other PHP XML extensions. To get the URL, you'll need to access the url attribute of the media:content node:
<media:content duration="95" medium="video" type="video/mp4"
url="http://brightcove.meta.nascar.com.edgesuite.net/vod/etc"/>
Target the first <media:content> node using
$xml->channel->item[$i]->children($namespaces['media'])->content[0]
and get its attributes:
$m_attrs =
$xml->channel->item[$i]->children($namespaces['media'])->content[0]->attributes();
You can then access the url attribute:
echo "URL: " . $m_attrs["url"] . "\n";
Your code should thus be:
$titleid = $xml->channel->item[$i]->children($namespaces['bc'])->titleid;
$m_attrs = $xml->channel->item[$i]->children($namespaces['media'])->content[0]->attributes();
$url = $m_attrs["url"];
$html .= "<h3>$title</h3>$description<p>$pubDate<p>$link<p>Video ID: $titleid<p> (etc.)";

Collect Form Data, insert in xml fields to post to Payment Gateway

I need to take payment information from a form and place it in XML and then post it to the payment gateway server. I am rather a novice at best and I am not sure of the easiest way to do this.
I have successfully been able to post to the payment gateway by manually entering the info into the XML on a static php file, so I know the XML is correct, the only real issue for me would be finding the easiest way to take form data and place into the XML.
Below is a sample of the php file and the XML.
<?php
$TransactionId = intval( date(Yms). rand(1,9) . rand(0,9) . rand(0,9) . rand(0,9) . rand(0,9). rand(0,9) );
$MerchantId="111111";
$TerminalId="111111";
$ApiPassword="111111";
$private_key="asdfasghgfdhggdfgs";
$ApiPassword_encrypt=hash('sha256',$ApiPassword);
$xmlReq='<?xml version="1.0" encoding="UTF-8" ?>
<TransactionRequest xmlns="https://test.processing.com/securePayments/direct/v1/processor.php">
<Language>ENG</Language>
<Credentials>
<MerchantId>'.$MerchantId.'</MerchantId>
<TerminalId>'.$TerminalId.'</TerminalId>
<TerminalPassword>'.$ApiPassword_encrypt.'</TerminalPassword>
</Credentials>
<TransactionType>LP001</TransactionType>
<TransactionId>'.$TransactionId.'</TransactionId>
<ReturnUrl page="http://www.website.net/response.php">
<Param>
<Key>inv</Key>
<Value>'.$TransactionId.'</Value>
</Param>
</ReturnUrl>
<CurrencyCode>USD</CurrencyCode>
<TotalAmount>44450</TotalAmount>
<CardDetails>
<CardHolderName>John Smith</CardHolderName>
<CardNumber>4653111111111111</CardNumber>
<CardExpireMonth>01</CardExpireMonth>
<CardExpireYear>15</CardExpireYear>
<CardType>VI</CardType>
<CardSecurityCode>030</CardSecurityCode>
<CardIssuingBank>UNKNOWN</CardIssuingBank>
<CardIssueNumber></CardIssueNumber>
</CardDetails>
</TransactionRequest>';
$signature_key=trim($private_key.$ApiPassword.$TransactionId);
$signature=base64_encode(hash_hmac("sha256", trim($xmlReq), $signature_key, True));
$encodedMessage=base64_encode($xmlReq);
markup your static xml with some sort of placeholder like {{key}}. then use this function to fill your xml:
<?php
function fill_template($tpl, $values = array()) {
$find = array();
preg_match_all("/\\{\\{([^}]+)\\}\\}/", $tpl, &$find);
foreach ($find[1] as $x => $key) {
$repl = '';
if (isset($values[$key])) {
$repl = $values[$key];
}
$tpl = str_replace($find[0][$x], $repl);
}
return $tpl;
}
?>
the $values parameter should contain the values from $_POST, along with whatever other values you need to set:
<?php
$payment_map = array('MerchantId' => 'xxx', 'TerminalId' => 'xxx');
$payment_map = array_merge($payment_map, $_POST);
$xml_template = "your markedup xml";
$xml = fill_template($xml_template, $payment_map);
?>
this may not be the most elegant solution but it should get you moving.
(obviously you'll want to validate form data and encode it into proper xml characters if necessary.)

Help with Exchange 2010 EWS (API) and/or PHP's NuSOAP library?

Just to be clear before continuing: using PHP's built-in SOAP class is unfortunately not an option here (production server's PHP is not built with it, and won't be).
I'm trying to use EWS to allow me to authenticate users for a completely external server application. LDAP authentication has been disallowed. I have verified my EWS wsdl is correct via http://www.testexchangeconnectivity.com/, a Microsoft autodiscover tool. The contents of the WSDL can be found here: http://pastebin.org/214070
The server is using SSL, and is using the default authentication method for EWS of "NTLM".
I've tried various code examples around the web, unfortunately I'm not well-versed in XML, SOAP, or cURL (which is pretty much all of the technology being used here). The current iteration of my code is found below:
<?php
include_once('./lib/nusoap.php');
$username = 'username#example.com';
$password = 'password';
$ews_url = 'https://owa.example.com/EWS/Exchange.asmx';
$soapclient = new nusoap_client($service, true);
$soapclient->setCredentials($username, $password, 'ntlm');
$soapclient->setUseCurl(true);
$soapclient->useHTTPPersistentConnection();
$soapclient->setCurlOption(CURLOPT_USERPWD, $username.':'.$password);
$soapclient->soap_defencoding = 'UTF-8';
$params = '<FindItem xmlns="http://schemas.microsoft.com/exchange/services/2006/messages"';
$params += ' xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" Traversal="Shallow">';
$params += ' <ItemShape>';
$params += ' <t:BaseShape>IdOnly</t:BaseShape>';
$params += ' <t:AdditionalProperties>';
$params += ' <t:FieldURI FieldURI="message:From"/>';
$params += ' <t:FieldURI FieldURI="item:Subject"/>';
$params += ' <t:FieldURI FieldURI="message:IsRead"/>';
$params += ' <t:FieldURI FieldURI="item:DateTimeReceived"/>';
$params += ' <t:FieldURI FieldURI="calendar:Start"/>';
$params += ' <t:FieldURI FieldURI="calendar:End"/>';
$params += ' <t:FieldURI FieldURI="calendar:Location"/>';
$params += ' <t:FieldURI FieldURI="task:Status"/>';
$params += ' <t:FieldURI FieldURI="task:DueDate"/>';
$params += ' </t:AdditionalProperties>';
$params += ' </ItemShape>';
$params += ' <IndexedPageItemView Offset="0" MaxEntriesReturned="5" BasePoint="Beginning"/>';
$params += ' <ParentFolderIds>';
$params += ' <t:DistinguishedFolderId Id="inbox"/>';
$params += ' </ParentFolderIds>';
$params += '</FindItem>';
$operation = 'FindItem';
$namespace = '';
$soapAction = '';
$headers = false;
$result = $soapclient->call($operation, $params, $namespace, $soapAction, $headers);
echo '<pre>'; print_r($result); echo '</pre>';
if($soapclient->fault){
echo 'FAULT: ';
echo '<pre>'; print_r($result); echo '</pre>';
}else{
$err = $soapclient->getError();
if ($err) {
echo '<p><b><u>Error</u>:</b><br />' . $err . '</p>';
}else{
echo 'Connection succeeded.';
}
}
?>
The actual issue I am having is that NuSOAP is returning a generic error message of: "no operations defined in the WSDL document!". From the looks of the WSDL, this seems incorrect and makes me believe I'm missing something in code. If I remove the actual client call in the code ($soapclient->call(...)), the code prints out "Connection succeeded.", but it does this with or without the attempted NTLM authentication code.
I've also tried using the "php-ews" project on my development machine (even though the same code would not work on the production server) and was also unable to access anything without receiving an error.
If anyone has any experience with any of these technologies and might be able to point out some clarification (or possible errors) I would greatly appreciate it. If any further clarification is needed on my part, please let me know.
UPDATE 1:
It seems one error in loading the WSDL is the NTLM Authentication. Using cURL alone (no NuSOAP) I was able to access the WSDL file and find out the server is redirecting to a different endpoint location (.../EWS/Services.wsdl).
Unfortunately, I've tried using the NuSOAP library's cURL ability and setting the same options through NuSOAP, and I am still getting the same generic error message as if NuSOAP is just unable to see/view/access the WSDL file. I believe it may still be NTLM Authentication as the cURL version takes a few moments to return (NTLM it a multi-step handshake process), whereas the NuSOAP client code is immediately returning the error message.
There's a few things you'll want to look at here.
There's an error in your call to the actual soap_client. You defined the endpoint in a variable called $ews_url, but then called the constructor with $service.
Why are you adding a string to a string in your $xml variable - perhaps in your haste you meant to concatenate instead? (operators: + vs .)
Using the following Wiki information directed to working with EWS in Java, it seems that Microsoft has yet again blundered in their implementation of a common protocol. The modification of types.xsd in this Wiki actually causes a problem, so ignore that change, but downloading a local copy of Services.wsdl and modifying it to point to your own server seems to work properly. http://www.bedework.org/trac/bedework/wiki/ExchangeWSlink text
The following code should work, so long as you have downloaded a local copy of your types.xsd, messages.xsd, and Services.wsdl - and modified the Services.wsdl file to add the required information relevant to your server. Make sure the local copies of those files are in the same folder on your server.
<?php
include_once('./lib/nusoap.php');
$username = 'username#example.com';
$password = 'password';
$endpoint = 'http://your.local.version/of/Services.wsdl';
$wsdl = true;
$soapclient = new nusoap_client($endpoint, $wsdl);
$soapclient->setCredentials($username, $password, 'ntlm');
$xml = '<FindItem xmlns="http://schemas.microsoft.com/exchange/services/2006/messages"';
$xml .= ' xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" Traversal="Shallow">';
$xml .= ' <ItemShape>';
$xml .= ' <t:BaseShape>IdOnly</t:BaseShape>';
$xml .= ' <t:AdditionalProperties>';
$xml .= ' <t:FieldURI FieldURI="message:From"/>';
$xml .= ' <t:FieldURI FieldURI="item:Subject"/>';
$xml .= ' <t:FieldURI FieldURI="message:IsRead"/>';
$xml .= ' <t:FieldURI FieldURI="item:DateTimeReceived"/>';
$xml .= ' <t:FieldURI FieldURI="calendar:Start"/>';
$xml .= ' <t:FieldURI FieldURI="calendar:End"/>';
$xml .= ' <t:FieldURI FieldURI="calendar:Location"/>';
$xml .= ' <t:FieldURI FieldURI="task:Status"/>';
$xml .= ' <t:FieldURI FieldURI="task:DueDate"/>';
$xml .= ' </t:AdditionalProperties>';
$xml .= ' </ItemShape>';
$xml .= ' <IndexedPageItemView Offset="0" MaxEntriesReturned="5" BasePoint="Beginning"/>';
$xml .= ' <ParentFolderIds>';
$xml .= ' <t:DistinguishedFolderId Id="inbox"/>';
$xml .= ' </ParentFolderIds>';
$xml .= '</FindItem>';
$operation = 'FindItem';
$result = $soapclient->call($operation, $xml);
echo '<pre>'; print_r($result); echo '</pre>';
?>
The solution all seems to stem from having a local copy of the main SOAP reference files, and fixing the Services.wsdl file. If you had access to the Exchange server, you might be able to modify the Services.wsdl file and everything could have worked as expected without all of this hassle. I cannot verify this, unfortunately.

Categories