Skip to content

Commit 5732be7

Browse files
committed
Merge pull request #90 from thybag/develop
Roll to master
2 parents 523f26d + 0dcc9ed commit 5732be7

File tree

9 files changed

+120
-74
lines changed

9 files changed

+120
-74
lines changed

License.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
The MIT License (MIT)
22

3-
Copyright (c) 2014 Carl Saggs
3+
Copyright (c) 2015 Carl Saggs
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

SharePointAPI.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* Simple PHP API for reading/writing and modifying SharePoint list items.
77
*
8-
* @version 0.6.2
8+
* @version 0.6.4
99
* @licence MIT License
1010
* @source: http://github.com/thybag/PHP-SharePoint-Lists-API
1111
*

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "thybag/php-sharepoint-lists-api",
3-
"version": "0.6.2",
3+
"version": "0.6.4",
44
"type": "library",
55
"description": "A simple PHP API to make working with SharePoint lists easy.",
66
"homepage": "https://github.com/thybag/PHP-SharePoint-Lists-API",

readme.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,3 +253,9 @@ If you are attempting to store a value in a "lookup" data type but for some reas
253253

254254
If you are getting this error it normally means that php_openssl (needed to curl https urls) is not enabled on your webserver. With many local websevers (such as XAMPP) you can simply open your php.ini file and uncomment the php_openssl line (ie. remove the ; before it).
255255

256+
Note: If you are using SharePoint Online and having SSL errors, please pull the latest version which has changed from SSL v3 to TLS for sharepoint online connections -
257+
258+
Add this line to your `composer.json` file.
259+
260+
"thybag/php-sharepoint-lists-api": "dev-develop"
261+

src/Thybag/Auth/SharePointOnlineAuth.php

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,7 @@ public function __doRequest($request, $location, $action, $version, $one_way = f
3232
curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
3333
curl_setopt($curl, CURLOPT_COOKIE, $this->authCookies);
3434

35-
// Connection requires CURLOPT_SSLVERSION set to 3
3635
curl_setopt($curl, CURLOPT_TIMEOUT, 10);
37-
curl_setopt($curl, CURLOPT_SSLVERSION, 3);
3836
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
3937

4038
// Useful for debugging
@@ -91,16 +89,32 @@ protected function configureAuthCookies($location) {
9189
// Send request and grab returned xml
9290
$result = $this->authCurl("https://login.microsoftonline.com/extSTS.srf", $xml);
9391

92+
9493
// Extract security token from XML
9594
$xml = new \DOMDocument();
9695
$xml->loadXML($result);
9796
$xpath = new \DOMXPath($xml);
97+
98+
// Register SOAPFault namespace for error checking
99+
$xpath->registerNamespace('psf', "http://schemas.microsoft.com/Passport/SoapServices/SOAPFault");
100+
101+
// Try to detect authentication errors
102+
$errors = $xpath->query("//psf:internalerror");
103+
if($errors->length > 0){
104+
$info = $errors->item(0)->childNodes;
105+
throw new \Exception($info->item(1)->nodeValue, $info->item(0)->nodeValue);
106+
}
107+
98108
$nodelist = $xpath->query("//wsse:BinarySecurityToken");
99109
foreach ($nodelist as $n){
100110
$token = $n->nodeValue;
101111
break;
102112
}
103113

114+
if(!isset($token)){
115+
throw new \Exception("Unable to extract token from authentiction request");
116+
}
117+
104118
// Send token to SharePoint online in order to gain authentication cookies
105119
$result = $this->authCurl($endpoint."/_forms/default.aspx?wa=wsignin1.0", $token, true);
106120

@@ -129,7 +143,6 @@ protected function extractAuthCookies($result){
129143
$authCookies[] = $loop[1];
130144
}
131145
}
132-
unset($authCookies[0]); // No need for first cookie
133146

134147
// Extract cookie name & payload and format in to cURL compatible string
135148
foreach($authCookies as $payload){
@@ -166,7 +179,7 @@ protected function authCurl($url, $payload, $header = false){
166179
curl_setopt($ch,CURLOPT_POSTFIELDS, $payload);
167180
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
168181

169-
curl_setopt($ch, CURLOPT_SSLVERSION, 3);
182+
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
170183
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
171184
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
172185

@@ -226,4 +239,4 @@ protected function generateSecurityToken($username, $password, $endpoint) {
226239
</s:Envelope>
227240
TOKEN;
228241
}
229-
}
242+
}

src/Thybag/Auth/SoapClientAuth.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ public function __doRequest($request, $location, $action, $version, $one_way = 0
8787
'User-Agent: PHP-SOAP',
8888
'Content-Type: text/xml; charset=utf-8',
8989
'SOAPAction: "' . $action . '"',
90-
'Content-Length: ' . strlen($request),
9190
'Expect: 100-continue',
9291
'Connection: Keep-Alive'
9392
);
@@ -105,7 +104,7 @@ public function __doRequest($request, $location, $action, $version, $one_way = 0
105104

106105
curl_setopt($ch, CURLOPT_USERPWD, $this->Username . ':' . $this->Password);
107106
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
108-
curl_setopt($ch, CURLOPT_SSLVERSION, 3);
107+
109108
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
110109
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
111110

src/Thybag/Auth/StreamWrapperHttpAuth.php

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,32 @@
11
<?php
22
namespace Thybag\Auth;
3+
/**
4+
* SoapClientAuth for accessing Web Services protected by HTTP authentication
5+
* Author: tc
6+
* Last Modified: 04/08/2011
7+
* Update: 14/03/2012 - Fixed issue with CURLAUTH_ANY not authenticating to NTLM servers
8+
* Download from: http://tcsoftware.net/blog/
9+
*
10+
* Copyright (C) 2011 tc software (http://tcsoftware.net)
11+
*
12+
* This program is free software: you can redistribute it and/or modify
13+
* it under the terms of the GNU General Public License as published by
14+
* the Free Software Foundation, either version 3 of the License, or
15+
* (at your option) any later version.
16+
*
17+
* This program is distributed in the hope that it will be useful,
18+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
* GNU General Public License for more details.
21+
*
22+
* You should have received a copy of the GNU General Public License
23+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
24+
*/
325

426
/**
527
* Class streamWrapperHttpAuth
28+
* @author tc
29+
* @copyright Copyright (C) 2011 tc software
630
*
731
* @package Thybag\Auth
832
*/
@@ -98,7 +122,6 @@ protected function postRequest($path, $authType = CURLAUTH_ANY) {
98122
);
99123
}
100124

101-
curl_setopt($this->curlHandle, CURLOPT_SSLVERSION, 3);
102125
curl_setopt($this->curlHandle, CURLOPT_SSL_VERIFYPEER, FALSE);
103126
curl_setopt($this->curlHandle, CURLOPT_SSL_VERIFYHOST, 2);
104127

@@ -109,7 +132,7 @@ protected function postRequest($path, $authType = CURLAUTH_ANY) {
109132
return $response;
110133
}
111134
else {
112-
throw new Exception(curl_error($this->curlHandle), curl_errno($this->curlHandle));
135+
throw new \Exception(curl_error($this->curlHandle), curl_errno($this->curlHandle));
113136
}
114137
}
115138
else {
@@ -118,15 +141,15 @@ protected function postRequest($path, $authType = CURLAUTH_ANY) {
118141
return $this->postRequest($path, CURLAUTH_NTLM);
119142
}
120143
else {
121-
throw new Exception ('Access Denied', 401);
144+
throw new \Exception ('Access Denied', 401);
122145
}
123146
}
124147
else {
125148
if (curl_errno($this->curlHandle) != 0) {
126-
throw new Exception(curl_error($this->curlHandle), curl_errno($this->curlHandle));
149+
throw new \Exception(curl_error($this->curlHandle), curl_errno($this->curlHandle));
127150
}
128151
else {
129-
throw new Exception('Error', $info['http_code']);
152+
throw new \Exception('Error', $info['http_code']);
130153
}
131154
}
132155
}

src/Thybag/Service/QueryObjectService.php

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ class QueryObjectService {
4444
*/
4545
private $fields = array();
4646

47+
/**
48+
* CAML Options for query
49+
*/
50+
private $options = NULL;
51+
4752
/**
4853
* Construct
4954
* Setup new query Object
@@ -135,6 +140,18 @@ public function using ($view) {
135140
return $this;
136141
}
137142

143+
/**
144+
* Options
145+
* Specify view to use when returning data.
146+
*
147+
* @param String $options "XML string of query options."
148+
* @return Ref to self
149+
*/
150+
public function options($options){
151+
$this->options = $options;
152+
return $this;
153+
}
154+
138155
/**
139156
* Sort
140157
* Specify order data should be returned in.
@@ -182,14 +199,15 @@ public function all_columns($exclude_hidden = true){ return $this->all_fields($e
182199
/**
183200
* get
184201
* Runs the specified query and returns a usable result.
185-
* @return Array: SharePoint List Data
202+
*
203+
* @return Array: SharePoint List Data
186204
*/
187-
public function get () {
205+
public function get ($options = NULL) {
188206

189207
// String = view, array = specific fields
190208
$view = (sizeof($this->fields) === 0) ? $this->view : $this->fields;
191209

192-
return $this->api->read($this->list_name, $this->limit, $this, $view);
210+
return $this->api->read($this->list_name, $this->limit, $this, $view, NULL, $this->options);
193211
}
194212

195213
/**

src/Thybag/SharePointAPI.php

Lines changed: 43 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Simple PHP API for reading/writing and modifying SharePoint list items.
88
*
99
* @author Carl Saggs
10-
* @version 0.6.2
10+
* @version 0.6.4
1111
* @licence MIT License
1212
* @source: http://github.com/thybag/PHP-SharePoint-Lists-API
1313
*
@@ -136,9 +136,10 @@ class SharePointAPI {
136136
* @param string $spUsername User account to authenticate with. (Must have read/write/edit permissions to given Lists)
137137
* @param string $spPassword Password to use with authenticating account.
138138
* @param string $spWsdl WSDL file for this set of lists ( sharepoint.url/subsite/_vti_bin/Lists.asmx?WSDL )
139-
* @param Whether to authenticate with NTLM
139+
* @param string $mode Authenticaton method to use (Defaults to basic auth, also supports SPONLINE & NTLM)
140+
* @param array $options Options for SoapClient
140141
*/
141-
public function __construct ($spUsername, $spPassword, $spWsdl, $mode = 'STANDARD') {
142+
public function __construct ($spUsername, $spPassword, $spWsdl, $mode = 'STANDARD', $options = array()) {
142143
// Check if required class is found
143144
assert(class_exists('SoapClient'));
144145

@@ -148,10 +149,9 @@ public function __construct ($spUsername, $spPassword, $spWsdl, $mode = 'STANDAR
148149
$this->spWsdl = $spWsdl;
149150

150151
/*
151-
* General options
152-
* NOTE: You can set all these parameters, see class ExampleSharePointAPI for an example)
152+
* defaults
153153
*/
154-
$options = array(
154+
$defaultOptions = array(
155155
'trace' => $this->soap_trace,
156156
'exceptions' => $this->soap_exceptions,
157157
'keep_alive' => $this->soap_keep_alive,
@@ -160,6 +160,8 @@ public function __construct ($spUsername, $spPassword, $spWsdl, $mode = 'STANDAR
160160
'compression' => $this->soap_compression,
161161
'encoding' => $this->internal_encoding,
162162
);
163+
// $options will overwrite defaults if provided
164+
$options = array_merge($defaultOptions, $options);
163165

164166
// Is login set?
165167
if (!empty($this->spUsername)) {
@@ -639,6 +641,36 @@ public function addAttachment ($list_name, $list_item_id, $file_name) {
639641
return true;
640642
}
641643

644+
/**
645+
* deleteAttachment
646+
* Remove an attachment from a SharePoint list item
647+
*
648+
* @param $list_name Name of list
649+
* @param $list_item_id ID of record item is attached to
650+
* @param $url
651+
*/
652+
public function deleteAttachment ($list_name, $list_item_id, $url) {
653+
// Wrap in CAML
654+
$CAML = '
655+
<DeleteAttachment xmlns="http://schemas.microsoft.com/sharepoint/soap/">
656+
<listName>' . $list_name . '</listName>
657+
<listItemID>' . $list_item_id . '</listItemID>
658+
<url>' . $url . '</url>
659+
</DeleteAttachment>';
660+
661+
$xmlvar = new \SoapVar($CAML, XSD_ANYXML);
662+
663+
// Attempt to run operation
664+
try {
665+
$this->soapClient->DeleteAttachment($xmlvar);
666+
} catch (\SoapFault $fault) {
667+
$this->onError($fault);
668+
}
669+
670+
// Return true on success
671+
return true;
672+
}
673+
642674
/**
643675
* getAttachment
644676
* Return an attachment from a SharePoint list item
@@ -835,12 +867,12 @@ public function getSortFromValue ($value) {
835867
$value = strtolower($value);
836868

837869
// Default is descending
838-
$sort = 'false';
870+
$sort = 'FALSE';
839871

840872
// Is value set to allow ascending sorting?
841873
if ($value == 'asc' || $value == 'true' || $value == 'ascending') {
842874
// Sort ascending
843-
$sort = 'true';
875+
$sort = 'TRUE';
844876
}
845877

846878
// Return it
@@ -1085,61 +1117,16 @@ public function getFieldVersions ($list, $id, $field) {
10851117
}
10861118
public function getColumnVersions ($list, $id, $field) { return $this->getFieldVersions($list, $id, $field); }
10871119

1088-
/**
1089-
* getItemVersions
1090-
* Get previous versions of an item
1091-
*
1092-
* @param $list Name or GUID of list
1093-
* @param $id ID of item to find versions for
1094-
* @return array | object
1095-
*/
1096-
public function getItemVersions ($list, $id, $exclude_hidden = true) {
1097-
$fields = $this->readListMeta($list, $exclude_hidden);
1098-
1099-
// Parse results
1100-
$results = array();
1101-
// Format data in to array or object
1102-
foreach ($fields as $counter => $field) {
1103-
// Modified always returns an error
1104-
if($field['name'] == 'Modified') { continue; }
1105-
1106-
// Get all the fields
1107-
$field_versions = $this->getFieldVersions($list, $id, $field['name']);
1108-
1109-
// Get the versions for each field
1110-
if(sizeof($field_versions) !== 0) {
1111-
foreach($field_versions as $key => $value) {
1112-
if($this->lower_case_indexs) {
1113-
$results[$key][strtolower($field['name'])] = $value[strtolower($field['name'])];
1114-
} else {
1115-
$results[$key][$field['name']] = $value[$field['name']];
1116-
}
1117-
}
1118-
//Make object if needed
1119-
if ($this->returnType === 1) settype($results[$counter], "object");
1120-
}
1121-
}
1122-
1123-
// Add error array if stuff goes wrong.
1124-
if (!isset($results)) $results = array('warning' => 'No data returned.');
1125-
1126-
return $results;
1127-
}
1128-
11291120
/**
11301121
* getVersions
1131-
* Get previous versions of an item or field
1122+
* Get previous versions of a field
11321123
*
11331124
* @param $list Name or GUID of list
11341125
* @param $id ID of item to find versions for
11351126
* @param $field optional name of column to get versions for
11361127
* @return array | object
11371128
*/
1138-
public function getVersions ($list, $id, $field = null, $exclude_hidden = true) {
1139-
if($field === null) {
1140-
return $this->getItemVersions($list, $id, $exclude_hidden);
1141-
} else {
1142-
return $this->getFieldVersions($list, $id, $field);
1143-
}
1129+
public function getVersions ($list, $id, $field = null) {
1130+
return $this->getFieldVersions($list, $id, $field);
11441131
}
11451132
}

0 commit comments

Comments
 (0)