Задача: Необходимо создать веб-сервис для публикации документов в Битриксе из SharePoint с необходимым набором методов для добавления, изменения и удаления записей.
Создала папку ws в корне сайта, в ней папку spdoc для определенного веб-сервиса.
Папка должна быть настроена на пустой шаблон Битрикса, в котором содержится только #WORK_AREA#.
В ней index.php
<?php
require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/header.php");
if (CModule::IncludeModule("webservice")) {
require($_SERVER["DOCUMENT_ROOT"] . "/ws/spdoc/spdoc.php");
$webservice = new CWebService();
if (!$webservice->RegisterWebService('CGenericWSDLSpdoc')) {
throw new Exception('Couldn't register webservice');
}
$result = $webservice->SOAPServerProcessRequest('spdoc.ws');
if (!$result) {
throw new Exception('Couldn't process request');
}
$response = $webservice->GetSOAPServerResponse('spdoc.ws');
echo $response;
} else {
throw new Exception('Couldn't initialize webservice');
}
Файл wsdl.php формирует страницу web-service
<?php
ini_set('display_errors', 1);
require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/header.php");
if (CModule::IncludeModule("webservice") ) {
require($_SERVER["DOCUMENT_ROOT"] . "/ws/spdoc/spdoc.php");
$webservice = new CWebService();
if (!$webservice->RegisterWebService('CGenericWSDLSpdoc')) {
throw new Exception('Couldn't register webservice');
}
$wsdl = $webservice->GetWSDL('spdoc.ws');
if (!$wsdl) {
throw new Exception('Couldn't create WSDL');
}
echo $wsdl;
} else {
throw new Exception('Couldn't initialize webservice');
}
Файл spdoc.php реализует инициализацию веб-сервиса и методы.
<?php
class createFile
{
var $mimeType;
var $fileName;
var $fileSize;
var $fileContent;
}
class cInputSp
{
var $group; //Группа документа
var $subject; //Название
var $method; //Доп. информация
var $file_a; //Архив приложений
}
class CGenericWSDLSpdoc extends IWebService
{
var $paramInfoBlock = array(
'IBLOCK_ID' => 18, // код ID основного информационного блока для добавления документов
'IBLOCK_GROUP' => 19 // код ID информационного блока для групп документов
);
function _trim(&$obInput){
$a_class = get_class($obInput);
$attribs = get_class_vars($a_class);
foreach ($attribs as $key=>$val){
if (is_string($obInput->$key)){
$obInput->$key = trim($obInput->$key);
}
}
}
function loadAttachFile ($file, $nameFile, &$errString) {
// функция загружает файл на диск во временный файл и подготавливает массив для записи файла в инфоблок
$this ->_trim($file);
if (empty($file->fileName) or $file->fileName == '?') return false; // file
if (empty($file->fileContent)) {$errString .= 'No file content: '.$file->fileName.'. '; return false;}
if (empty($file->mimeType)) {$errString .= 'No mime-type: '.$file->fileName.'. '; return false;}
$fileArray = array();
$tmpFile = $_SERVER["DOCUMENT_ROOT"]."/ws/spdoc/".$nameFile;
($f = fopen($tmpFile,'w+b')) or die('Error create temp file.' );
if (!$fileArray['size'] = fwrite($f,base64_decode($file->fileContent))) {$errString .= 'Error write temp file. '; return false;}
fclose($f);
$fileArray['name'] = $file->fileName;
$fileArray['tmp_name'] = $tmpFile;
$fileArray['type'] = $file->mimeType;
return $fileArray;
}
function publication($data)
{
global $USER;
$this ->_trim($data);
$errString = '';
if ( CModule::IncludeModule("iblock") ) {
// в инфоблоке уже много документов и есть символьное поле NUMBER с номером документа в Битриксе. В Битриксе своя нумерация, отличная от SP.
// Нужно найти последний номер публикации и присвоить новой записи следующий
// last number of publication
$arSelect = Array("ID", "PROPERTY_NUMBER");
$arFilter = Array("IBLOCK_ID" => $this->paramInfoBlock ['IBLOCK_ID'],"INCLUDE_SUBSECTIONS" => "Y");
global $DB;
$strSql = '
SELECT MAX(CAST(VALUE AS UNSIGNED)) AS max_num
FROM b_iblock_element_property AS a
INNER JOIN b_iblock_property AS b ON b.ID = a.IBLOCK_PROPERTY_ID
WHERE b.CODE = "NUMBER"
';
$NumberPubl = $DB->Query($strSql)->getNext();
$NumberPubl = $NumberPubl['max_num'] + 1;
// Проверяю имя группы документа в инфоблоке с группами документов и создаю нужную группу, если ее нет
$arSelect = Array("ID", "NAME");
$arFilter = Array("IBLOCK_ID" => $this->paramInfoBlock['IBLOCK_GROUP'],"INCLUDE_SUBSECTIONS" => "Y","NAME"=>$data->group);
$items = CIBlockElement::GetList(false, $arFilter, false, false, $arSelect);
$idGroup = 0;
if ($lastEl = $items->GetNextElement()){
$idGroup = $lastEl->fields['ID'];
}
else {
$el = new CIBlockElement;
$arLoadProductArray = Array(
"MODIFIED_BY" => $USER->GetID(), // элемент изменен текущим пользователем
"IBLOCK_ID" => intval($this->paramInfoBlock ['IBLOCK_GROUP']),
"NAME" => $data->group,
"ACTIVE" => "Y", // активен
"PREVIEW_TEXT" => '',
"DETAIL_TEXT" => '',
);
$idGroup = $el->Add($arLoadProductArray);
}
// создаю элемент инфоблока
$el = new CIBlockElement;
$PROP = array();
$PROP['NUMBER'] = $NumberPubl;
$PROP['METHOD'] = $data->method;
$PROP['GROUP'] = $idGroup;
if ($fileArray = $this->loadAttachFile($data->file_a, 'file_a', $errString) )
$PROP['FILE'] = $fileArray; //
$arLoadProductArray = Array(
"MODIFIED_BY" => $USER->GetID(), // элемент изменен текущим пользователем
"IBLOCK_ID" => intval($this->paramInfoBlock ['IBLOCK_ID']),
"PROPERTY_VALUES" => $PROP,
"NAME" => $data->subject,
"ACTIVE" => "Y", // активен
"PREVIEW_TEXT" => '',
"DETAIL_TEXT" => '',
);
$product_id = 0;
if ($product_id = $el->Add($arLoadProductArray))
{return array('id' => intval($product_id),'errString'=> $errString);}
else
{return array('id' => intval($product_id),'errString'=> $errString.'Can not add record to DB');}
}
}
function delete($id)
{
if (CModule::IncludeModule("iblock")) {
if (!CIBlockElement::Delete($id)) {
return false;
}
else
return true;
}
}
function GetWebServiceDesc()
{
// описание web-service
$wsdesc = new CWebServiceDesc();
$wsdesc->wsname = "spdoc.ws";
$wsdesc->wsclassname = "CGenericWSDLSpdoc";
$wsdesc->wsdlauto = true;
$wsdesc->wsendpoint = 'http://'.$_SERVER['HTTP_HOST'].'/ws/spdoc/index.php';
$wsdesc->wstargetns = CWebService::GetDefaultTargetNS();
$wsdesc->classTypes = array();
$wsdesc->structTypes = array();
/* this tryed to be loaded into a class */
$wsdesc->classTypes["createFile"] =
array(
"mimeType" => array("varType" => "string", "strict" => "no"),// свойство "strict" => "no" указывается, если поле необязательно к заполнению
"fileName" => array("varType" => "string", "strict" => "no"),
"fileSize" => array("varType" => "string", "strict" => "no"),
"fileContent" => array("varType" => "string", "strict" => "no"),
);
$wsdesc->classTypes["cInputSp"] =
array(
"group" => array("varType" => "string"),
"subject" => array("varType" => "string"),
"method" => array("varType" => "string"),
"file_a" => array("varType" => "createFile")
);
$wsdesc->classes = array(
"CGenericWSDLSpdoc" => array(
"delete" => array(
"type" => "public",
"name" => "delete",
"description" => "",
"input" => array(
"id" => array("varType" => "integer"),
),
"output" => array(
"result" => array("varType" => "boolean")
)
),
"publication" => array(
"type" => "public",
"name" => "publication",
"description" => "Adds item with data, [out] array(integer id, string errString if attached file have name and haven't content or mime type)
([in] class (
group - группа,
subject - наименование,
method - способ закупки,
file_a - архив с приложениями)",
"input" => array(
"data" => array("varType" => "cInputSp")
),
"output" => array(
"id" => array("varType" => "integer"),
"errString" => array("varType" => "string"),
)
)
));
return $wsdesc;
}
}
Созданный веб-сервис имеет Initial WSDL /ws/spdoc/wsdl.php
Проверяем веб-сервис любым клиентом, например soapUI.
Приведенный выше код проверен.