Skip to content

Instantly share code, notes, and snippets.

@kj187
Created January 30, 2014 10:46
Show Gist options
  • Save kj187/8706171 to your computer and use it in GitHub Desktop.
Save kj187/8706171 to your computer and use it in GitHub Desktop.
<?php
namespace Thybag;
/**
* SharepointAPI
*
* Simple PHP API for reading/writing and modifying SharePoint list items.
*
* @author Carl Saggs
* @version 2012.12.24
* @licence MIT License
* @source: http://github.com/thybag/PHP-SharePoint-Lists-API
*
* Tested against the sharepoint 2007 API
*
* WSDL file needed will be located at: sharepoint.url/subsite/_vti_bin/Lists.asmx?WSDL
*
* Usage:
* $sp = new \Thybag\SharePointAPI('<username>','<password>','<path_to_WSDL>');
*
* Read:
* $sp->read('<list_name>');
* $sp->read('<list_name>', 500); // Return 500 records
* $sp->read('<list_name>', NULL, array('<col_name>'=>'<col_value>'); // Filter on col_name = col_value
* $sp->read('<list_name>', NULL, NULL, '{FAKE-GUID00-0000-000}'); // Return list items with view (specified via GUID)
* $sp->read('<list_name>', NULL, NULL, NULL, array('col_name'=>'asc|desc'));
*
* Query:
* $sp->query('<list_name>')->where('type','=','dog')->and_where('age','>','5')->limit(10)->sort('age','asc')->get();
*
* Write: (insert)
* $sp->write('<list_name>', array('<col_name>' => '<col_value>','<col_name_2>' => '<col_value_2>'));
*
* WriteMultiple:
* $sp->writeMultiple('<list_name>', array(
* array('Title' => 'New item'),
* array('Title' => 'New item 2')
* ));
*
* Update:
* $sp->update('<list_name>','<row_id>', array('<col_name>'=>'<new_data>'));
*
* UpdateMultiple:
* $sp->updateMultiple('<list_name>', array(
* array('ID'=>1, 'Title' => 'new name'),
* array('ID'=>2, 'Title' => 'New name 2')
* ));
*
* Delete:
* $sp->delete('<list_name>','<row_id>');
*
* CRUD can be used for multiple actions on a single list.
* $list = $api->CRUD('<list_name>');
* $list->read(10);
* $list->create(array('<col_name>' => '<col_value>','<col_name_2>' => '<col_value_2>'));
*/
class SharePointAPI {
/**
* Username for SP auth
*/
private $spUsername = '';
/**
* Password for SP auth
*/
private $spPassword = '';
/**
* Location of WSDL
*/
private $spWsdl = '';
/**
* Return type (default: 0)
*
* 0 = Array
* 1 = Object
*/
private $returnType = 0;
/**
* Make all indexs lower-case
*/
private $lower_case_indexs = TRUE;
/**
* Maximum rows to return from a List
*/
private $MAX_ROWS = 10000;
/**
* Place holder for soapClient/SOAP client
*/
private $soapClient = NULL;
/**
* Whether requests shall be traced
* (compare: http://de.php.net/manual/en/soapclient.soapclient.php )
*/
protected $soap_trace = TRUE;
/**
* Whether SOAP errors throw exception of type SoapFault
*/
protected $soap_exceptions = TRUE;
/**
* Kee-Alive HTTP setting (default: FALSE)
*/
protected $soap_keep_alive = FALSE;
/**
* SOAP version number (default: SOAP_1_1)
*/
protected $soap_version = SOAP_1_1;
/**
* Compression
* Example: SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP
*/
protected $soap_compression = 0;
/**
* Cache behaviour for WSDL content (default: WSDL_CACHE_NONE for better debugging)
*/
protected $soap_cache_wsdl = WSDL_CACHE_NONE;
/**
* Internal (!) encoding (not SOAP; default: UTF-8)
*/
protected $internal_encoding = 'UTF-8';
/**
* Constructor
*
* @param string $spUsername User account to authenticate with. (Must have read/write/edit permissions to given Lists)
* @param string $spPassword Password to use with authenticating account.
* @param string $spWsdl WSDL file for this set of lists ( sharepoint.url/subsite/_vti_bin/Lists.asmx?WSDL )
* @param Whether to authenticate with NTLM
*/
public function __construct ($spUsername, $spPassword, $spWsdl, $NTLM = FALSE) {
// Check if required class is found
assert(class_exists('SoapClient'));
// Set data from parameters in this class
$this->spUsername = $spUsername;
$this->spPassword = $spPassword;
$this->spWsdl = $spWsdl;
/*
* General options
* NOTE: You can set all these parameters, see class ExampleSharePointAPI for an example)
*/
$options = array(
'trace' => $this->soap_trace,
'exceptions' => $this->soap_exceptions,
'keep_alive' => $this->soap_keep_alive,
'soap_version' => $this->soap_version,
'cache_wsdl' => $this->soap_cache_wsdl,
'compression' => $this->soap_compression,
'encoding' => $this->internal_encoding,
);
// Is login set?
if (!empty($this->spUsername)) {
// Then set login data
$options['login'] = $this->spUsername;
$options['password'] = $this->spPassword;
}
// Create new SOAP Client
try {
if ((isset($options['login'])) && ($NTLM === TRUE)) {
// Ensure SoapClientAuth is included
#require_once 'SoapClientAuth.php';
// If using authentication then use the custom SoapClientAuth class.
$this->soapClient = new \Thybag\Auth\SoapClientAuth($this->spWsdl, $options);
} else {
$this->soapClient = new \SoapClient($this->spWsdl, $options);
}
} catch (SoapFault $fault) {
// If we are unable to create a Soap Client display a Fatal error.
throw new \Exception('Unable to locate WSDL file. faultcode=' . $fault->getCode() . ',faultstring=' . $fault->getMessage());
}
}
/**
* Calls methods on SOAP object
*
* @param string $methodName Name of method to call
* @param array $methodParams Parameters to handle over
* @return mixed $returned Returned values
*/
public final function __call ($methodName, array $methodParams) {
/*
* Is soapClient set? This check may look double here but in later
* developments it might help to trace bugs better and it avoids calls
* on wrong classes if $soapClient got set to something not SoapClient.
*/
if (!$this->soapClient instanceof \SoapClient) {
// Is not set
throw new \Exception('Variable soapClient is not a SoapClient class, have: ' . gettype($this->soapClient), 0xFF);
}
// Is it a "SOAP callback"?
if (substr($methodName, 0, 2) == '__') {
// Is SoapClient's method
$returned = call_user_func_array(array($this->soapClient, $methodName), $methodParams);
} else {
// Call it
$returned = $this->soapClient->__call($methodName, $methodParams);
}
// Return any values
return $returned;
}
/**
* Returns an array of all lists
*
* @param array $keys Keys which shall be included in final JSON output
* @param array $params Only search for lists with given criteria (default: 'hidden' => 'False')
* @param bool $isSensetive Whether to look case-sensetive (default: TRUE)
* @return array $newLists An array with given keys from all lists
*/
public function getLimitedLists (array $keys, array $params = array('hidden' => 'False'), $isSensetive = TRUE) {
// Get the full list back
$lists = $this->getLists();
// Init new list and look for all matching entries
$newLists = array();
foreach ($lists as $entry) {
// Default is found
$isFound = TRUE;
// Search for all criteria
foreach ($params as $key => $value) {
// Is it found?
if ((isset($entry[$key])) && ((($isSensetive === TRUE) && ($value != $entry[$key])) || (strtolower($value) != strtolower($entry[$key])))) {
// Is not found
$isFound = FALSE;
break;
}
}
// Add it?
if ($isFound === TRUE) {
// Generate new entry array
$newEntry = array();
foreach ($keys as $key) {
// Add this key
$newEntry[$key] = $entry[$key];
}
// Add this new array
$newLists[] = $newEntry;
unset($newEntry);
}
}
// Return finished array
return $newLists;
}
/**
* Get Lists
* Return an array containing all avaiable lists within a given sharepoint subsite.
* Use "set return type" if you wish for this data to be provided as an object.
*
* @return array (array) | array (object)
*/
public function getLists () {
// Query Sharepoint for full listing of it's lists.
$rawXml = '';
try {
$rawXml = $this->soapClient->GetListCollection()->GetListCollectionResult->any;
} catch (SoapFault $fault) {
$this->onError($fault);
}
// Load XML in to DOM document and grab all list items.
$nodes = $this->getArrayFromElementsByTagName($rawXml, 'List');
// Format data in to array or object
foreach ($nodes as $counter => $node) {
foreach ($node->attributes as $attribute => $value) {
$idx = ($this->lower_case_indexs) ? strtolower($attribute) : $attribute;
$results[$counter][$idx] = $node->getAttribute($attribute);
}
// Make object if needed
if ($this->returnType === 1) {
settype($results[$counter], 'object');
}
}
// Add error array if stuff goes wrong.
if (!isset($results)) {
$results = array('warning' => 'No data returned.');
}
return $results;
}
/**
* Read List MetaData (Column configurtion)
* Return a full listing of columns and their configurtion options for a given sharepoint list.
*
* @param $list_name Name or GUID of list to return metaData from.
* @param $hideInternal TRUE|FALSE Attempt to hide none useful columns (internal data etc)
* @param $ignoreHiddenAttribute TRUE|FALSE Ignores 'Hidden' attribute if it is set to 'TRUE' - DEBUG ONLY!!!
* @return Array
*/
public function readListMeta ($list_name, $hideInternal = TRUE, $ignoreHiddenAttribute = FALSE) {
// Ready XML
$CAML = '
<GetList xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<listName>' . $list_name . '</listName>
</GetList>
';
// Attempt to query Sharepoint
$rawXml = '';
try {
$rawXml = $this->soapClient->GetList(new \SoapVar($CAML, XSD_ANYXML))->GetListResult->any;
} catch (\SoapFault $fault) {
$this->onError($fault);
}
// Load XML in to DOM document and grab all Fields
$nodes = $this->getArrayFromElementsByTagName($rawXml, 'Field');
// Format data in to array or object
foreach ($nodes as $counter => $node) {
// Empty inner_xml
$inner_xml = '';
// Attempt to hide none useful feilds (disable by setting second param to FALSE)
if ($hideInternal && ($node->getAttribute('Type') == 'Lookup' || $node->getAttribute('Type') == 'Computed' || ($node->getAttribute('Hidden') == 'TRUE' && $ignoreHiddenAttribute === FALSE))) {
continue;
}
// Get Attributes
foreach ($node->attributes as $attribute => $value) {
$idx = ($this->lower_case_indexs) ? strtolower($attribute) : $attribute;
$results[$counter][$idx] = $node->getAttribute($attribute);
}
// Get contents (Raw xml)
foreach ($node->childNodes as $childNode) {
$inner_xml .= $node->ownerDocument->saveXml($childNode);
}
$results[$counter]['value'] = $inner_xml;
// Make object if needed
if ($this->returnType === 1) {
settype($results[$counter], 'object');
}
// If hiding internal is enabled and 'id' is not set, remove this element
if ($hideInternal && !isset($results[$counter]['id'])) {
// Then it has to be an "internal"
unset($results[$counter]);
}
}
// Add error array if stuff goes wrong.
if (!isset($results)) {
$results = array('warning' => 'No data returned.');
}
// Return a XML as nice clean Array or Object
return $results;
}
/**
* Read
* Use's raw CAML to query sharepoint data
*
* @param String $list_name
* @param int $limit
* @param Array $query
* @param String (GUID) $view "View to display results with."
* @param Array $sort
* @param String $options "XML string of query options."
*
* @return Array
*/
public function read ($list_name, $limit = NULL, $query = NULL, $view = NULL, $sort = NULL, $options = NULL) {
// Check limit is set
if ($limit < 1 || is_null($limit)) {
$limit = $this->MAX_ROWS;
}
// Create Query XML is query is being used
$xml_options = '';
$xml_query = '';
// Setup Options
if ($query instanceof SPQueryObj) {
$xml_query = $query->getCAML();
} else {
if (!is_null($view)) {
$xml_options .= '<viewName>' . $view . '</viewName>';
}
if (!is_null($query)) {
$xml_query .= $this->whereXML($query); // Build Query
}
if (!is_null($sort)) {
$xml_query .= $this->sortXML($sort);
}
}
// If query is required
if (!empty($xml_query)) {
$xml_options .= '<query><Query>' . $xml_query . '</Query></query>';
}
/*
* Setup basic XML for quering a sharepoint list.
* If rowLimit is not provided sharepoint will defualt to a limit of 100 items.
*/
$CAML = '
<GetListItems xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<listName>' . $list_name . '</listName>
<rowLimit>' . $limit . '</rowLimit>
' . $xml_options . '
<queryOptions xmlns:SOAPSDK9="http://schemas.microsoft.com/sharepoint/soap/" >
<QueryOptions>
' . $options . '
</QueryOptions>
</queryOptions>
</GetListItems>';
// Ready XML
$xmlvar = new \SoapVar($CAML, XSD_ANYXML);
$result = NULL;
// Attempt to query Sharepoint
try {
$result = $this->xmlHandler($this->soapClient->GetListItems($xmlvar)->GetListItemsResult->any);
} catch (\SoapFault $fault) {
$this->onError($fault);
}
// Return a XML as nice clean Array
return $result;
}
/**
* ReadFromFolder
* Use's raw CAML to query sharepoint data from a folder
*
* @param String $listName
* @param String $folderName
* @param bool $isLibrary
* @param String $limit
* @param String $query
* @param String $view
* @param String $sort
*
* @return Array
*/
public function readFromFolder($listName, $folderName = '', $isLibrary = false, $limit = NULL, $query = NULL, $view = NULL, $sort = NULL) {
return $this->read($listName, $limit, $query, $view, $sort, "<Folder>" . ($isLibrary ? '' : 'Lists/') . $listName . '/' . $folderName . "</Folder>" );
}
/**
* Write
* Create new item in a sharepoint list
*
* @param String $list_name Name of List
* @param Array $data Assosative array describing data to store
* @return Array
*/
public function write ($list_name, array $data) {
return $this->writeMultiple($list_name, array($data));
}
// Alias (Identical to above)
public function add ($list_name, array $data) { return $this->write($list_name, $data); }
public function insert ($list_name, array $data) { return $this->write($list_name, $data); }
/**
* WriteMultiple
* Batch create new items in a sharepoint list
*
* @param String $list_name Name of List
* @param Array of arrays Assosative array's describing data to store
* @return Array
*/
public function writeMultiple ($list_name, array $items) {
return $this->modifyList($list_name, $items, 'New');
}
// Alias (Identical to above)
public function addMultiple ($list_name, array $items) { return $this->writeMultiple($list_name, $items); }
public function insertMultiple ($list_name, array $items) { return $this->writeMultiple($list_name, $items); }
/**
* Update
* Update/Modifiy an existing list item.
*
* @param String $list_name Name of list
* @param int $ID ID of item to update
* @param Array $data Assosative array of data to change.
* @return Array
*/
public function update ($list_name, $ID, array $data) {
// Add ID to item
$data['ID'] = $ID;
return $this->updateMultiple($list_name, array($data));
}
// aliases
public function edit($list_name, $ID, array $data) { return $this->update ($list_name, $ID, $data); }
/**
* UpdateMultiple
* Batch Update/Modifiy existing list item's.
*
* @param String $list_name Name of list
* @param Array of arrays of assosative array of data to change. Each item MUST include an ID field.
* @return Array
*/
public function updateMultiple ($list_name, array $items) {
return $this->modifyList($list_name, $items, 'Update');
}
// aliases
public function editMultiple($list_name, array $items) { return $this->updateMultiple ($list_name, $items); }
/**
* Delete
* Delete an existing list item.
*
* @param String $list_name Name of list
* @param int $ID ID of item to delete
* @param array $data An array of additional required key/value pairs for the item to delete e.g. FileRef => URL to file.
* @return Array
*/
public function delete ($list_name, $ID, array $data = array()) {
return $this->deleteMultiple($list_name, array($ID), array($ID => $data));
}
/**
* DeleteMultiple
* Delete existing multiple list items.
*
* @param String $list_name Name of list
* @param array $IDs IDs of items to delete
* @param array $data An array of arrays of additional required key/value pairs for each item to delete e.g. FileRef => URL to file.
* @return Array
*/
public function deleteMultiple ($list_name, array $IDs, array $data = array()) {
/*
* change input "array(ID1, ID2, ID3)" to "array(array('id' => ID1),
* array('id' => ID2), array('id' => ID3))" in order to be compatible
* with modifyList.
*
* For each ID also check if we have any additional data. If so then
* add it to the delete data.
*/
$deletes = array();
foreach ($IDs as $ID) {
$delete = array('ID' => $ID);
// Add additional data if available
if (!empty($data[$ID])) {
foreach ($data[$ID] as $key => $value) {
$delete[$key] = $value;
}
}
$deletes[] = $delete;
}
// Return a XML as nice clean Array
return $this->modifyList($list_name, $deletes, 'Delete');
}
public function addAttachment ($list_name, $list_item_id, $file_name) {
// base64 encode file
$attachment = base64_encode(file_get_contents($file_name));
// Wrap in CAML
$CAML = '
<AddAttachment xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<listName>' . $list_name . '</listName>
<listItemID>' . $list_item_id . '</listItemID>
<fileName>' . $file_name . '</fileName>
<attachment>' . $attachment . '</attachment>
</AddAttachment>';
$xmlvar = new \SoapVar($CAML, XSD_ANYXML);
// Attempt to run operation
try {
$this->soapClient->AddAttachment($xmlvar);
} catch (\SoapFault $fault) {
$this->onError($fault);
}
// Return true on success
return true;
}
public function getAttachments ($list_name, $list_item_id) {
// Wrap in CAML
$CAML = '
<GetAttachmentCollection xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<listName>' . $list_name . '</listName>
<listItemID>' . $list_item_id . '</listItemID>
</GetAttachmentCollection>';
$xmlvar = new \SoapVar($CAML, XSD_ANYXML);
// Attempt to run operation
try {
$rawXml = $this->soapClient->GetAttachmentCollection($xmlvar)->GetAttachmentCollectionResult->any;
} catch (\SoapFault $fault) {
$this->onError($fault);
}
// Load XML in to DOM document and grab all list items.
$nodes = $this->getArrayFromElementsByTagName($rawXml, 'Attachment');
$attachments = array();
// Format data in to array or object
foreach ($nodes as $counter => $node) {
$attachments[] = $node->textContent;
}
// Return Array of attachment URLs
return $attachments;
}
/**
* setReturnType
* Change the dataType used to store List items.
* Array or Object.
*
* @param $type
*/
public function setReturnType ($type) {
if (trim(strtolower($type)) == 'object') {
$this->returnType = 1;
} else {
$this->returnType = 0;
}
}
/**
* lowercaseIndexs
* Enable or disable automically lowercasing indexs for returned data.
* (By defualt this is enabled to avoid users having to worry about the case attributers are in)
* Array or Object.
*
* @param $enable TRUE|FALSE
*/
public function lowercaseIndexs ($enable) {
$this->lower_case_indexs = ($enable === TRUE);
}
/**
* Query
* Create a query against a list in sharepoint
*
* Build querys as $sp->query('my_list')->where('score','>',15)->and_where('year','=','9')->get();
*
* @param List name / GUID number
* @return \Thybag\Service\QueryObjectService
*/
public function query ($table) {
return new \Thybag\Service\QueryObjectService($table, $this);
}
/**
* CRUD
* Create a simple Create, Read, Update, Delete Wrapper around a specific list.
*
* @param $list_name Name of list to provide CRUD for.
* @return \Thybag\Service\ListService
*/
public function CRUD ($list_name) {
return new \Thybag\Service\ListService($list_name, $this);
}
/**
* "Getter" for an array of nodes from given "raw XML" and tag name
*
* @param string $rawXml "Raw XML" data
* @param string $tag Name of tag
* @param string $namespace Optional namespace
* @return array $nodes An array of XML nodes
*/
private function getArrayFromElementsByTagName ($rawXml, $tag, $namespace = NULL) {
// Get DOM instance and load XML
$dom = new \DOMDocument();
$dom->loadXML($rawXml);
// Is namespace set?
if (!is_null($namespace)) {
// Use it
$nodes = $dom->getElementsByTagNameNS($tag, $namespace);
} else {
// Get nodes
$nodes = $dom->getElementsByTagName($tag);
}
// Return nodes list
return $nodes;
}
/**
* xmlHandler
* Transform the XML returned from SOAP in to a useful datastructure.
* By Defualt all sharepoint items will be represented as arrays.
* Use setReturnType('object') to have them returned as objects.
*
* @param $rawXml XML DATA returned by SOAP
* @return Array( Array ) | Array( Object )
*/
private function xmlHandler ($rawXml) {
// Use DOMDocument to proccess XML
$results = $this->getArrayFromElementsByTagName($rawXml, '#RowsetSchema', '*');
$resultArray = array();
// Proccess Object and return a nice clean assoaitive array of the results
foreach ($results as $i => $result) {
$resultArray[$i] = array();
foreach ($result->attributes as $attribute => $value) {
$idx = ($this->lower_case_indexs) ? strtolower($attribute) : $attribute;
// Re-assign all the attributes into an easy to access array
$resultArray[$i][str_replace('ows_', '', $idx)] = $result->getAttribute($attribute);
}
/*
* ReturnType 1 = Object.
* If set, change array in to an object.
*
* Feature based on implementation by dcarbone (See: https://github.com/dcarbone/ )
*/
if ($this->returnType === 1) {
settype($resultArray[$i], 'object');
}
}
// Check some values were actually returned
if (count($resultArray) == 0) {
$resultArray = array(
'warning' => 'No data returned.',
'raw_xml' => $rawXml
);
}
return $resultArray;
}
/**
* Query XML
* Generates XML for WHERE Query
*
* @param Array $q array('<col>' => '<value_to_match_on>')
* @return XML DATA
*/
private function whereXML (array $q) {
$queryString = '';
$counter = 0;
foreach ($q as $col => $value) {
$counter++;
$queryString .= '<Eq><FieldRef Name="' . $col . '" /><Value Type="Text">' . htmlspecialchars($value) . '</Value></Eq>';
// Add additional "and"s if there are multiple query levels needed.
if ($counter >= 2) {
$queryString = '<And>' . $queryString . '</And>';
}
}
return '<Where>' . $queryString . '</Where>';
}
/**
* "Getter" for sort ascending ("true") or descending ("false") from given value
*
* @param string $value Value to be checked
* @return string $sort "true" for ascending, "false" (default) for descending
*/
public function getSortFromValue ($value) {
// Make all lower-case
$value = strtolower($value);
// Default is descending
$sort = 'false';
// Is value set to allow ascending sorting?
if ($value == 'asc' || $value == 'true' || $value == 'ascending') {
// Sort ascending
$sort = 'true';
}
// Return it
return $sort;
}
/**
* Sort XML
* Generates XML for sort
*
* @param Array $sort array('<col>' => 'asc | desc')
* @return XML DATA
*/
private function sortXML (array $sort) {
// On no count, no need to sort
if (count($sort) == 0) {
return '';
}
$queryString = '';
foreach ($sort as $col => $value) {
$queryString .= '<FieldRef Name="' . $col . '" Ascending="' . $this->getSortFromValue($value) . '" />';
}
return '<OrderBy>' . $queryString . '</OrderBy>';
}
/**
* modifyList
* Perform an action on a sharePoint list to either update or add content to it.
* This method will use prepBatch to generate the batch xml, then call the sharepoint SOAP API with this data
* to apply the changes.
*
* @param $list_name SharePoint List to update
* @param $items Arrary of new items or item changesets.
* @param $method New/Update/Delete
* @return Array|Object
*/
public function modifyList ($list_name, array $items, $method) {
// Get batch XML
$commands = $this->prepBatch($items, $method);
// Wrap in CAML
$CAML = '
<UpdateListItems xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<listName>' . $list_name . '</listName>
<updates>
<Batch ListVersion="1" OnError="Continue">
' . $commands . '
</Batch>
</updates>
</UpdateListItems>';
$xmlvar = new \SoapVar($CAML, XSD_ANYXML);
$result = NULL;
// Attempt to run operation
try {
$result = $this->xmlHandler($this->soapClient->UpdateListItems($xmlvar)->UpdateListItemsResult->any);
} catch (\SoapFault $fault) {
$this->onError($fault);
}
// Return a XML as nice clean Array
return $result;
}
/**
* prepBatch
* Convert an array of new items or changesets in to XML commands to be run on
* the sharepoint SOAP API.
*
* @param $items array of new items/changesets
* @param $method New/Update/Delete
* @return XML
*/
public function prepBatch (array $items, $method) {
// Check if method is supported
assert(in_array($method, array('New', 'Update', 'Delete')));
// Get var's needed
$batch = '';
$counter = 1;
// Foreach item to be converted in to a SharePoint Soap Command
foreach ($items as $data) {
// Wrap item in command for given method
$batch .= '<Method Cmd="' . $method . '" ID="' . $counter . '">';
// Add required attributes
foreach ($data as $itm => $val) {
// Add entry
$batch .= '<Field Name="' . $itm . '">' . htmlspecialchars($val) . '</Field>' . PHP_EOL;
}
$batch .= '</Method>';
// Inc counter
$counter++;
}
// Return XML data.
return $batch;
}
/**
* onError
* This is called when sharepoint throws an error and displays basic debug info.
*
* @param $fault Error Information
* @throws \Exception Puts data from $fault into an other exception
*/
private function onError (SoapFault $fault) {
$more = '';
if (isset($fault->detail->errorstring)) {
$more = 'Detailed: ' . $fault->detail->errorstring;
}
throw new \Exception('Error (' . $fault->faultcode . ') ' . $fault->faultstring . ',more=' . $more);
}
/**
* magicLookup: Helper method
*
* If you know the name of the item you wish to link to in the lookup field, this helper method
* can be used to perform the lookup for you.
*
* @param $sp Active/current instance of sharepointAPI
* @param $name Name of item you wish lookup to reference
* @param $list Name of list item lookup is linked to.
*
* @return "lookup" value sharepoint will accept
*/
public function magicLookup ($name, $list) {
//Perform lookup for specified item on specified list
$find = $this->read($list, null, array('Title' => $name));
//If we get a result (and there is only one of them) return it in "Lookup" format
if (isset($find[0]) && count($find) === 1) {
settype($find[0], 'array');//Set type to array in case API is in object mode.
if ($this->lower_case_indexs) {
return static::lookup($find[0]['id'], $find[0]['title']);
} else {
return static::lookup($find[0]['ID'], $find[0]['Title']);
}
} else {
//If we didnt find anything / got to many, throw exception
throw new \Exception('Unable to perform automated lookup for value in ' . $list . '.');
}
}
/**
* dateTime: Helper method
* Format date for use by sharepoint
* @param $date (Date to be handled by strtotime)
* @param $timestamp. If first parameter is unix timestamp, set this to true
*
*@return date sharepoint will accept
*/
public static function dateTime ($date, $timestamp = FALSE) {
return ($timestamp) ? date('c',$date) : date('c', strtotime($date));
}
/**
* lookup: Helper method
* Format data to be used in lookup datatype
* @param $id ID of item in other table
* @param $title Title of item in other table (this is optional as sharepoint doesnt complain if its not provided)
*
* @return string "lookup" value sharepoint will accept
*/
public static function lookup ($id, $title = '') {
return $id . (($title !== '') ? ';#' . $title : '');
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment