Skip to content

Commit

Permalink
Merge branch 'release/1.0.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
mikaelcom committed Mar 23, 2017
2 parents 0f3396e + 7239144 commit 778e777
Show file tree
Hide file tree
Showing 44 changed files with 20,808 additions and 450 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
wsdltophp.phar
vendor
composer.lock
samples/_*.php
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# CHANGELOG

## 1.0.0
- Create update schema as substitutionGroup attribute is not handled by the native PHP SoapClient class
- Update generated classes thanks to PackageGenerator fixed issues
- Working samples have been added
- Implement a method into the SoapClient class in order to remove useless empty request tags

## 0.0.8
- Minor readme update

Expand Down
31 changes: 29 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@
# PackageEws365
This package has been generated from the [Office 365 Exchange Web Services](wsdl/services.wsdl) WSDL using the [PackageGenerator](https://github.com/WsdlToPhp/PackageGenerator) project.

The complete list of operations is available at the [Office Dev Center](https://msdn.microsoft.com/fr-fr/library/office/bb409286(v=exchg.150).aspx).

# Summary
- [Generating again the package](#generating-again-the-package)
- [How to use the generated package?](#how-to-use-the-generated-package)
- [Install the project](#install-the-project)
- [Learn from the tutorial](#learn-from-the-tutorial)
- [Start from the samples](#start-from-the-samples)
- [GetServerTimeZones](samples/GetServerTimeZones.php)
- [Need support or having a question?](#need-support-or-having-a-question)

# Generating again the package
Expand All @@ -37,10 +38,36 @@ $ composer update
## Learn from the tutorial
Start looking into the auto-generated [tutorial.php](tutorial.php) file. This file contains the starting code to use this package. In addition it contains all the operations provided by the Exchange Web Services and the way to call them.

## Determine your Office 365 endpoint action location
Determining the Office 365 endpoint action location can be tricky so below is indicated 2 ways to do it. This location must be defined in the `setLocation` call into the sample files.
The default location has been defined so it might work fine with you too. If not, you should try determining it. If you don't understand, don't hesitate to contact me at contact@wsdltophp.com.

### Manually from the endpoint itself
You should be able to get the endpoint action location from the services.wsdl by opening your browser and browsing to [outlook.office365.com/EWS/Exchange.asmx](https://outlook.office365.com/EWS/Exchange.asmx).
You must enter your Office 365 credentials then it should display a page where it indicates something such as `svcutil.exe https://**.outlook.com/EWS/Services.wsdl`.
This is in the `https://**.outlook.com/EWS/Services.wsdl` that you can find at the end the endpoint action location such as `<soap:address location="**https://outlook.office365.com/EWS/Exchange.asmx**" />`.

### From your Office 365 account
Following this [Tech Blog article](http://blog.skysoft-is.com/?p=78), I simply used the endpoint location action indicated in the article as https://pod51036.outlook.com/ews/services.wsdl and it worked :).

## Start from the samples
Sample scripts are available under the [samples](samples) folder:

- [GetServerTimeZones](samples/GetServerTimeZones.php)
- [Inbox](samples/inbox)
- [FindItems](samples/inbox/FindItems.php)
- [FindUnreadItems](samples/inbox/FindUnreadItems.php)
- [GetItem](samples/inbox/GetItem.php)
- [Contact](samples/contact)
- [FindItems](samples/contact/FindItems.php)
- [GetItem](samples/contact/GetItem.php)
- [Calendar](samples/calendar)
- [FindItems](samples/calendar/FindItems.php)
- [GetItem](samples/calendar/GetItem.php)
- [Task](samples/task)
- [CreateItem](samples/task/CreateItem.php)
- [FindItems](samples/task/FindItems.php)
- [GetItem](samples/task/GetItem.php)

# Need support or having a question?
We can help you understand how to use it and how to customize it. Feel free to contact us at contact@wsdltophp.com.
We can help you understand how to use it and how to customize it. Feel free to contact us at contact@wsdltophp.com.
76 changes: 76 additions & 0 deletions SoapClient/SoapClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,80 @@
*/
class SoapClient extends \SoapClient
{
/**
* @var string
*/
protected $lastModifiedRequest;
/**
* @param string $request
* @param string $location
* @param string $action
* @param string $version
* @param number $one_way
* @return mixed
*/
public function __doRequest($request, $location, $action, $version, $one_way = 0)
{
$this->removeEmptyTags($request);
return parent::__doRequest($this->__getLastRequest(), $location, $action, $version, $one_way);
}
/**
* Returns last request
* @see SoapClient::__getLastRequest()
* @return string
*/
public function __getLastRequest()
{
return $this->lastModifiedRequest;
}
/**
* Sets last request values
* @param string $_lastRequest
* @return string
*/
public function __setLastRequest($lastRequest)
{
return ($this->lastModifiedRequest = $lastRequest);
}
/**
* Removes empty tags from XML
* @param string $xml
* @param array $exceptTags
* @return string
*/
private function removeEmptyTags($xml, $exceptTags = array())
{
if (!empty($xml)) {
$dom = new \DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;
if ($dom->loadXML($xml) && $dom->hasChildNodes()) {
$mainNode = $dom->childNodes->item(0);
self::removeEmptyTagsFromDomNode($mainNode, $exceptTags);
$xml = $dom->saveXML($mainNode);
}
}
return $this->__setLastRequest($xml);
}
/**
* Removes empty tags from \DOMNode
* @uses RemoveEmptyRequestTags::removeEmptyTagsFromDomNode()
* @param \DOMNode $domNode
* @return void
*/
private static function removeEmptyTagsFromDomNode(\DOMNode &$domNode, $exceptTags = array())
{
if ($domNode->hasChildNodes()) {
foreach ($domNode->childNodes as $childNode) {
self::removeEmptyTagsFromDomNode($childNode, $exceptTags);
}
} elseif (trim($domNode->nodeValue) === '' && !in_array($domNode->nodeName, $exceptTags) && $domNode->attributes->length === 0) {
/**
* As the parent might not have returned an empty value as it contained this child
* we go process back the parent to be sure that he validated as not empty
*/
$parentNode = $domNode->parentNode;
$domNode->parentNode->removeChild($domNode);
self::removeEmptyTagsFromDomNode($parentNode, $exceptTags);
}
}
}
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "wsdltophp/package-ews365",
"description": "Package generated from wsdl/services.wsdl using wsdltophp/packagegenerator",
"description": "Package generated from wsdl/services.updated.wsdl using wsdltophp/packagegenerator",
"require": {
"php": ">=5.3.3",
"ext-soap": "*",
Expand All @@ -12,4 +12,4 @@
"SoapClient\\": "./SoapClient/"
}
}
}
}
5 changes: 3 additions & 2 deletions generate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,18 @@ rm -rf $DEST/src/ \

# package informations
php wsdltophp.phar generate:package \
--urlorpath=$DEST"/wsdl/services.wsdl" \
--urlorpath=$DEST"/wsdl/services.updated.wsdl" \
--destination=$DEST \
--composer-name="wsdltophp/package-ews365" \
--composer-settings="autoload.psr-4.SoapClient\:./SoapClient/" \
--composer-settings="require-dev.wsdltophp/packagegenerator:~2.0" \
--addcomments="author:WsdlToPhp <contact@wsdltophp.com>" \
--soapclient="\SoapClient\SoapClientBase" \
--prefix="Ews";

# generate package
php wsdltophp.phar generate:package \
--urlorpath=$DEST"/wsdl/services.wsdl" \
--urlorpath=$DEST"/wsdl/services.updated.wsdl" \
--destination=$DEST \
--composer-name="wsdltophp/package-ews365" \
--composer-settings="autoload.psr-4.SoapClient\:./SoapClient/" \
Expand Down
10 changes: 6 additions & 4 deletions samples/GetServerTimeZones.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
use WsdlToPhp\PackageBase\AbstractSoapClientBase;
use Ews\EnumType\EwsExchangeVersionType;
use Ews\EwsClassMap;
use Ews\StructType\EwsRequestServerVersion;
use Ews\StructType\EwsGetServerTimeZonesType;

/**
* Your Office 365 login, like {id}@{id}.onmicrosoft.com
* Your Office 365 login
*/
define('EWS_WS_LOGIN', '');
/**
Expand All @@ -37,11 +39,11 @@
/**
* Configure the SoapHeader, each header's method begins with "setSoapHeader".
*/
$get->setSoapHeaderRequestServerVersion(new \Ews\StructType\EwsRequestServerVersion(EwsExchangeVersionType::VALUE_EXCHANGE_2013_SP_1));
$get->setSoapHeaderRequestServerVersion(new EwsRequestServerVersion(EwsExchangeVersionType::VALUE_EXCHANGE_2013_SP_1));
/**
* Send the request, you can customize the request by modifiying the new \Ews\StructType\EwsGetServerTimeZonesType() instance
* Send the request, you can customize the request by modifiying the new EwsGetServerTimeZonesType() instance
*/
$result = $get->GetServerTimeZones(new \Ews\StructType\EwsGetServerTimeZonesType());
$result = $get->GetServerTimeZones(new EwsGetServerTimeZonesType());

/**
* Debug informations provided by the utility methods
Expand Down
99 changes: 99 additions & 0 deletions samples/calendar/FindItems.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php
/**
* Composer autoload
*/
require_once __DIR__ . '/../../vendor/autoload.php';

/**
* Used classes
*/
use WsdlToPhp\PackageBase\AbstractSoapClientBase;
use Ews\EnumType\EwsExchangeVersionType;
use Ews\EwsClassMap;
use Ews\StructType\EwsFindItemType;
use Ews\StructType\EwsItemResponseShapeType;
use Ews\EnumType\EwsDefaultShapeNamesType;
use Ews\StructType\EwsNonEmptyArrayOfBaseFolderIdsType;
use Ews\EnumType\EwsDistinguishedFolderIdNameType;
use Ews\EnumType\EwsItemQueryTraversalType;
use Ews\StructType\EwsDistinguishedFolderIdType;
use Ews\StructType\EwsRequestServerVersion;

/**
* Your Office 365 login
*/
define('EWS_WS_LOGIN', '***************************');
/**
* Your Office 365 passowrd
*/
define('EWS_WS_PASSWORD', '************');

/**
* Minimal options in order to instanciate the ServiceType named Get
*/
$options = array(
AbstractSoapClientBase::WSDL_URL => __DIR__ . '/../../wsdl/services.updated.wsdl',
AbstractSoapClientBase::WSDL_CLASSMAP => EwsClassMap::get(),
AbstractSoapClientBase::WSDL_LOGIN => EWS_WS_LOGIN,
AbstractSoapClientBase::WSDL_PASSWORD => EWS_WS_PASSWORD,
);

/**
* Instanciation of the ServiceType get that gather all the operations beginnig with "get".
*/
$find = new \Ews\ServiceType\EwsFind($options);
$find->setLocation('https://pod51036.outlook.com/ews/Exchange.asmx');
/**
* Configure the SoapHeader, each header's method begins with "setSoapHeader".
*/
$find->setSoapHeaderRequestServerVersion(new EwsRequestServerVersion(EwsExchangeVersionType::VALUE_EXCHANGE_2013_SP_1));
/**
* Send the request
*/
$itemType = new EwsFindItemType();
$itemShape = new EwsItemResponseShapeType(EwsDefaultShapeNamesType::VALUE_ALL_PROPERTIES);
$itemType
->setItemShape($itemShape)
->setParentFolderIds(new EwsNonEmptyArrayOfBaseFolderIdsType(null, new EwsDistinguishedFolderIdType(EwsDistinguishedFolderIdNameType::VALUE_CALENDAR)))
->setTraversal(EwsItemQueryTraversalType::VALUE_SHALLOW);
$result = $find->FindItem($itemType);

/**
* Debug informations provided by the utility methods
*/
if (false) {
echo 'XML Request: ' . $find->getLastRequest() . "\r\n";
echo 'Headers Request: ' . $find->getLastRequestHeaders() . "\r\n";
echo 'XML Response: ' . $find->getLastResponse() . "\r\n";
echo 'Headers Response: ' . $find->getLastResponseHeaders() . "\r\n";
}

if ($result !== false) {
/**
* Display the Calendar items if there is at least one:
*
* Event with subject "***" starts at "2017-03-15T08:00:00-06:00" and ends at "2017-03-15T08:30:00-06:00" with timezone "(UTC-07:00) Mountain Time (US & Canada)"
* Event with subject "***" starts at "2017-03-15T08:00:00-06:00" and ends at "2017-03-15T08:30:00-06:00" with timezone "(UTC-07:00) Mountain Time (US & Canada)"
* ... etc
*/
foreach($result->getResponseMessages()->getFindItemResponseMessage() as $message) {
$events = $message->getRootFolder()->getItems()->getCalendarItem();
if(is_array($events)) {
foreach($events as $item) {
echo PHP_EOL . sprintf('Event with subject "%s" starts at "%s" and ends at "%s" with timezone "%s"',
$item->getSubject(),
$item->getStartWallClock(),
$item->getEndWallClock(),
$item->getTimeZone());
}
} else {
echo PHP_EOL . 'No event found';
}
echo PHP_EOL;
}
} else {
/**
* In this case, we get the \SoapFault object
*/
print_r($find->getLastErrorForMethod('\Ews\ServiceType\EwsFind::FindItem'));
}
Loading

0 comments on commit 778e777

Please sign in to comment.