<?php
|
|
|
|
namespace SparkLib\UPS;
|
|
|
|
use SparkLib\UPS\Ship\AddressType,
|
|
SparkLib\UPS\Ship\BillShipperType,
|
|
SparkLib\UPS\Ship\CodeDescriptionType,
|
|
SparkLib\UPS\Ship\ContactType,
|
|
SparkLib\UPS\Ship\CurrencyMonetaryType,
|
|
SparkLib\UPS\Ship\DimensionsType,
|
|
SparkLib\UPS\Ship\InternationalFormType,
|
|
SparkLib\UPS\Ship\LabelImageFormatType,
|
|
SparkLib\UPS\Ship\LabelStockSizeType,
|
|
SparkLib\UPS\Ship\LabelSpecificationType,
|
|
SparkLib\UPS\Ship\PackageDeclaredValueType,
|
|
SparkLib\UPS\Ship\PackageServiceOptionsType,
|
|
SparkLib\UPS\Ship\PackageType,
|
|
SparkLib\UPS\Ship\PackageWeightType,
|
|
SparkLib\UPS\Ship\PaymentInfoType,
|
|
SparkLib\UPS\Ship\PhoneType,
|
|
SparkLib\UPS\Ship\ProductType,
|
|
SparkLib\UPS\Ship\ProducerType,
|
|
SparkLib\UPS\Ship\ProductWeightType,
|
|
SparkLib\UPS\Ship\RateInfoType,
|
|
SparkLib\UPS\Ship\ReferenceNumberType,
|
|
SparkLib\UPS\Ship\RequestType,
|
|
SparkLib\UPS\Ship\ServiceAccessToken,
|
|
SparkLib\UPS\Ship\ServiceType,
|
|
SparkLib\UPS\Ship\ShipperType,
|
|
SparkLib\UPS\Ship\ShipAddressType,
|
|
SparkLib\UPS\Ship\ShipFromType,
|
|
SparkLib\UPS\Ship\ShipToType,
|
|
SparkLib\UPS\Ship\ShipmentChargeType,
|
|
SparkLib\UPS\Ship\ShipmentType,
|
|
SparkLib\UPS\Ship\ShipmentRequest,
|
|
SparkLib\UPS\Ship\ShipmentServiceOptionsType,
|
|
SparkLib\UPS\Ship\SoldToType,
|
|
SparkLib\UPS\Ship\UltimateConsigneeType,
|
|
SparkLib\UPS\Ship\UnitOfMeasurementType,
|
|
SparkLib\UPS\Ship\UnitType,
|
|
SparkLib\UPS\Ship\UPSSecurity,
|
|
SparkLib\UPS\Ship\UsernameToken;
|
|
|
|
use Exception,
|
|
SoapClient,
|
|
SoapHeader,
|
|
SoapFault,
|
|
DOMDocument;
|
|
|
|
class Ship {
|
|
|
|
private $_wsdl = UPS_SHIP_WSDL;
|
|
private $_schema = UPS_SCHEMA;
|
|
private $_client;
|
|
private $_options;
|
|
private $_request;
|
|
private $_response;
|
|
private $_destination;
|
|
|
|
private $_lineItems;
|
|
private $_serviceType;
|
|
private $_shipper;
|
|
private $_international;
|
|
private $_PAK = false;
|
|
private $_shipFrom;
|
|
private $_shipTo;
|
|
private $_shipmentMethod;
|
|
private $_payment;
|
|
private $_label;
|
|
private $_totalValue;
|
|
private $_package;
|
|
private $_packages = [];
|
|
private $_products = [];
|
|
|
|
private $_rates = [];
|
|
|
|
public $upsCodes = [
|
|
1 => 'Next Day Air',
|
|
2 => '2nd Day Air',
|
|
3 => 'Ground',
|
|
7 => 'Worldwide Express',
|
|
8 => 'Worldwide Expedited',
|
|
11 => 'Standard',
|
|
12 => '3 Day Select',
|
|
13 => 'Next Day Air Saver',
|
|
14 => 'Next Day Air Early AM',
|
|
59 => '2nd Day Air AM',
|
|
54 => 'Worldwide Express Plus',
|
|
65 => 'UPS Saver'
|
|
];
|
|
|
|
public function __construct() {
|
|
$Request = new RequestType();
|
|
$Shipment = new ShipmentType();
|
|
$LabelSpecification = new LabelSpecificationType();
|
|
|
|
$this->_request = new ShipmentRequest($Request, $Shipment, $LabelSpecification);
|
|
|
|
$this->_totalValue = 0;
|
|
}
|
|
|
|
public function setDestination($dest) {
|
|
$this->_destination = $dest;
|
|
}
|
|
|
|
public function allowPakRates() {
|
|
$this->_PAK = true;
|
|
}
|
|
|
|
public function createPackage() {
|
|
if ($this->_package instanceOf PackageType)
|
|
throw new Exception ('Add current package before creating a new one.');
|
|
$this->_package = new PackageType();
|
|
}
|
|
|
|
public function setPackageSize($l, $w, $h, $units = 'IN') {
|
|
if ($this->_package == null)
|
|
throw new Exception ('Create package before setting size.');
|
|
|
|
if ($this->_international === null)
|
|
throw new Exception ('Set shipment destination before adding packages');
|
|
|
|
$weight = $this->_package->PackageWeight->Weight;
|
|
|
|
if (! isset($weight))
|
|
throw new Exception ('Set package weight before setting size');
|
|
|
|
if ($this->_PAK && $this->_international && $weight <= constant('\PAK_RATE_THRESHOLD')) {
|
|
$this->_package->setPackaging(new CodeDescriptionType('04'));
|
|
} else {
|
|
$this->_package->setPackaging(new CodeDescriptionType('02'));
|
|
$this->_package->setDimensions(
|
|
new DimensionsType(new CodeDescriptionType($units), $l, $w, $h)
|
|
);
|
|
}
|
|
}
|
|
|
|
public function setPackageWeight($weight, $units = 'LBS') {
|
|
|
|
if ($this->_package == null)
|
|
throw new Exception ('Create package before setting weight.');
|
|
|
|
$this->_package->setPackageWeight(
|
|
new PackageWeightType(new CodeDescriptionType($units), $weight)
|
|
);
|
|
}
|
|
|
|
public function setPackageValue($value = null) {
|
|
|
|
if ($this->_package == null)
|
|
throw new Exception ('Create package before setting value.');
|
|
|
|
$DeclaredValue = new PackageDeclaredValueType();
|
|
$DeclaredValue->setCurrencyCode('USD');
|
|
|
|
if ($value)
|
|
$DeclaredValue->setMonetaryValue($value);
|
|
else
|
|
$DeclaredValue->setMonetaryValue($this->_totalValue);
|
|
|
|
$PackageServiceOptions = new PackageServiceOptionsType();
|
|
$PackageServiceOptions->setDeclaredValue($DeclaredValue);
|
|
|
|
$this->_package->setPackageServiceOptions($PackageServiceOptions);
|
|
}
|
|
|
|
public function setReferenceNumber($num) {
|
|
|
|
$ReferenceNumber = new ReferenceNumberType();
|
|
$ReferenceNumber->setValue($num);
|
|
$ReferenceNumber->setBarCodeIndicator(true);
|
|
|
|
if ($this->_international) {
|
|
$this->_request->Shipment->setReferenceNumber($ReferenceNumber);
|
|
} else if (count($this->_packages) == 0) {
|
|
throw new Exception ('Add packages before setting reference number.');
|
|
} else {
|
|
foreach ($this->_packages as &$package)
|
|
$package->setReferenceNumber($ReferenceNumber);
|
|
}
|
|
}
|
|
|
|
public function addPackage() {
|
|
array_push($this->_packages, $this->_package);
|
|
$this->_package = null;
|
|
}
|
|
|
|
public function addItem($value, $qty = 1, $desc = 'Merchandise',
|
|
$tariff = '', $origin = 'US') {
|
|
|
|
if (count($this->_products) < 50) {
|
|
// Sanitize description
|
|
$desc = substr(preg_replace("/[^\w\d ]/i", '', $desc), 0, 35);
|
|
|
|
// Make sure value isn't too precise
|
|
$value = round($value, 6);
|
|
|
|
$this->_totalValue += $value;
|
|
|
|
$product = new ProductType();
|
|
$measure = new UnitOfMeasurementType('PCS');
|
|
$units = new UnitType($qty, $measure, $value);
|
|
$product->setDescription($desc);
|
|
$product->setUnit($units);
|
|
$product->setCommodityCode($tariff);
|
|
$product->setOriginCountryCode($origin);
|
|
|
|
array_push($this->_products, $product);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Functions for handling Shipper node.
|
|
*/
|
|
private function initShipper() {
|
|
if (!isset($this->_shipper))
|
|
$this->_shipper = new ShipperType();
|
|
}
|
|
|
|
public function setShipperAddress($street, $city, $state, $postal,
|
|
$country, $account) {
|
|
$this->initShipper();
|
|
$this->initForms();
|
|
|
|
$address = new ShipAddressType($street, $city, $state, $postal, $country);
|
|
|
|
$this->_shipper->setAddress($address);
|
|
$this->_shipper->setShipperNumber($account);
|
|
|
|
$Address = new AddressType($street, $city, $state, null, $postal, $country);
|
|
$this->_request->Shipment
|
|
->ShipmentServiceOptions
|
|
->InternationalForms
|
|
->Contacts
|
|
->Producer
|
|
->setAddress($Address);
|
|
}
|
|
|
|
public function setShipperPhone($phone) {
|
|
$phone = preg_replace('/[^0-9]/', '', $phone);
|
|
|
|
$this->initShipper();
|
|
$this->_shipper->setPhone(new PhoneType($phone));
|
|
}
|
|
|
|
public function setShipperName($name, $company = null) {
|
|
$this->initShipper();
|
|
$this->initForms();
|
|
|
|
if ($company) {
|
|
$this->_shipper->setName($company);
|
|
$this->_shipper->setAttentionName($name);
|
|
$this->_shipper->setCompanyDisplayableName($company);
|
|
|
|
$this->_request->Shipment
|
|
->ShipmentServiceOptions
|
|
->InternationalForms
|
|
->Contacts
|
|
->Producer
|
|
->setCompanyName($company);
|
|
$this->_request->Shipment
|
|
->ShipmentServiceOptions
|
|
->InternationalForms
|
|
->Contacts
|
|
->Producer
|
|
->setAttentionName($name);
|
|
} else {
|
|
$this->_shipper->setName($name);
|
|
$this->_shipper->setAttentionName($name);
|
|
$this->_shipper->setCompanyDisplayableName($name);
|
|
|
|
$this->_request->Shipment
|
|
->ShipmentServiceOptions
|
|
->InternationalForms
|
|
->Contacts
|
|
->Producer
|
|
->setCompanyName($name);
|
|
$this->_request->Shipment
|
|
->ShipmentServiceOptions
|
|
->InternationalForms
|
|
->Contacts
|
|
->Producer
|
|
->setAttentionName($name);
|
|
}
|
|
}
|
|
|
|
public function setShipperTaxID($taxId) {
|
|
$this->initShipper();
|
|
$this->_shipper->setTaxIdentificationNumber($taxId);
|
|
}
|
|
|
|
public function setShipperEmail($email) {
|
|
$this->initShipper();
|
|
$this->_shipper->setEMailAddress($email);
|
|
}
|
|
|
|
/**
|
|
* Functions for handling ShipFrom node.
|
|
*/
|
|
private function initShipFrom() {
|
|
if (!isset($this->_shipFrom))
|
|
$this->_shipFrom = new ShipFromType();
|
|
}
|
|
|
|
public function setShipFromAddress($street, $city, $state, $postal,
|
|
$country) {
|
|
$this->initShipFrom();
|
|
$address = new ShipAddressType($street, $city, $state, $postal, $country);
|
|
$this->_shipFrom->setAddress($address);
|
|
}
|
|
|
|
public function setShipFromPhone($phone) {
|
|
$phone = preg_replace('/[^0-9]/', '', $phone);
|
|
|
|
$this->initShipFrom();
|
|
$this->_shipFrom->setPhone(new PhoneType($phone));
|
|
}
|
|
|
|
public function setShipFromName($name, $company = null) {
|
|
$this->initShipFrom();
|
|
|
|
if ($company) {
|
|
$this->_shipFrom->setName($company);
|
|
$this->_shipFrom->setAttentionName($name);
|
|
$this->_shipFrom->setCompanyDisplayableName($company);
|
|
} else {
|
|
$this->_shipFrom->setName($name);
|
|
$this->_shipFrom->setAttentionName($name);
|
|
$this->_shipFrom->setCompanyDisplayableName($name);
|
|
}
|
|
}
|
|
|
|
public function setShipFromTaxID($taxId) {
|
|
$this->initShipFrom();
|
|
$this->_shipFrom->setTaxIdentificationNumber($taxId);
|
|
}
|
|
|
|
/**
|
|
* Functions for handling ShipTo node.
|
|
*/
|
|
private function initShipTo() {
|
|
if (!isset($this->_shipTo))
|
|
$this->_shipTo = new ShipToType();
|
|
}
|
|
|
|
public function setShipToAddress($street, $city, $state, $postal, $country) {
|
|
$this->initShipTo();
|
|
$this->initForms();
|
|
|
|
// Do some really basic validation on the postal code
|
|
if ($country == 'US') {
|
|
$postal = substr(preg_replace('/[^0-9]+/', '', $postal), 0, 5);
|
|
$this->_international = false;
|
|
} else if ($country == 'CA') {
|
|
$postal = substr(preg_replace('/[^0-9A-Za-z]+/', '', $postal), 0, 6);
|
|
$this->_international = true;
|
|
} else {
|
|
$postal = substr(preg_replace('/[^0-9A-Za-z]+/', '', $postal), 0, 9);
|
|
$this->_international = true;
|
|
}
|
|
|
|
// Street cannot be more than 35 characters long
|
|
if (is_array($street))
|
|
foreach ($street as &$s)
|
|
$s = substr($s, 0, 35);
|
|
else
|
|
$street = substr($street, 0, 35);
|
|
|
|
// Only US and Canada should have the state field set.
|
|
// Ireland should be set to IE because they don't have postal codes.
|
|
if ($country == 'IE')
|
|
$state = 'IE';
|
|
else if (! ($country == 'US' || $country == 'CA'))
|
|
$state = null;
|
|
|
|
$ShipAddress = new ShipAddressType($street, $city, $state, $postal, $country);
|
|
$this->_shipTo->setAddress($ShipAddress);
|
|
|
|
$UltimateConsigneeAddress = new AddressType($street, $city, $state, null, $postal, $country);
|
|
$this->_request->Shipment
|
|
->ShipmentServiceOptions
|
|
->InternationalForms
|
|
->Contacts
|
|
->UltimateConsignee
|
|
->setAddress($UltimateConsigneeAddress);
|
|
|
|
$SoldToAddress = new AddressType($street, $city, $state, null, $postal, $country);
|
|
$this->_request->Shipment
|
|
->ShipmentServiceOptions
|
|
->InternationalForms
|
|
->Contacts
|
|
->SoldTo
|
|
->setAddress($SoldToAddress);
|
|
}
|
|
|
|
public function setShipToPhone($phone) {
|
|
$phone = preg_replace('/[^0-9]/', '', $phone);
|
|
|
|
if ($phone) {
|
|
$this->initShipTo();
|
|
$this->_shipTo->setPhone(new PhoneType($phone));
|
|
}
|
|
}
|
|
|
|
public function setShipToName($name, $company = null) {
|
|
$this->initShipTo();
|
|
$this->initForms();
|
|
|
|
$name = substr($name, 0, 35);
|
|
|
|
if ($company) {
|
|
$company = substr($company, 0, 35);
|
|
|
|
$this->_shipTo->setName($company);
|
|
$this->_shipTo->setAttentionName($name);
|
|
$this->_shipTo->setCompanyDisplayableName($company);
|
|
$this->_request->Shipment
|
|
->ShipmentServiceOptions
|
|
->InternationalForms
|
|
->Contacts
|
|
->UltimateConsignee
|
|
->setCompanyName($company);
|
|
$this->_request->Shipment
|
|
->ShipmentServiceOptions
|
|
->InternationalForms
|
|
->Contacts
|
|
->SoldTo
|
|
->setName($company);
|
|
$this->_request->Shipment
|
|
->ShipmentServiceOptions
|
|
->InternationalForms
|
|
->Contacts
|
|
->SoldTo
|
|
->setAttentionName($name);
|
|
} else {
|
|
$this->_shipTo->setName($name);
|
|
$this->_shipTo->setAttentionName($name);
|
|
$this->_shipTo->setCompanyDisplayableName($name);
|
|
$this->_request->Shipment
|
|
->ShipmentServiceOptions
|
|
->InternationalForms
|
|
->Contacts
|
|
->UltimateConsignee
|
|
->setCompanyName($name);
|
|
$this->_request->Shipment
|
|
->ShipmentServiceOptions
|
|
->InternationalForms
|
|
->Contacts
|
|
->SoldTo
|
|
->setName($name);
|
|
$this->_request->Shipment
|
|
->ShipmentServiceOptions
|
|
->InternationalForms
|
|
->Contacts
|
|
->SoldTo
|
|
->setAttentionName($name);
|
|
}
|
|
}
|
|
|
|
public function setShipToEmail($email) {
|
|
$this->initShipTo();
|
|
$this->_shipTo->setEMailAddress($email);
|
|
}
|
|
|
|
public function addShipmentAccount($account) {
|
|
$transportation = new ShipmentChargeType();
|
|
$transportation->setType('01');
|
|
$transportation->setBillShipper(new BillShipperType($account));
|
|
|
|
$this->_payment = new PaymentInfoType($transportation);
|
|
}
|
|
|
|
public function setShippingMethod($serviceCode) {
|
|
$this->_serviceType = new ServiceType($serviceCode);
|
|
}
|
|
|
|
private function initForms() {
|
|
if (!isset($this->_request->Shipment->ShipmentServiceOptions->InternationalForms)) {
|
|
|
|
$Producer = new ProducerType();
|
|
$UltimateConsignee = new UltimateConsigneeType();
|
|
$SoldTo = new SoldToType();
|
|
|
|
$Contacts = new ContactType();
|
|
$Contacts->setProducer($Producer);
|
|
$Contacts->setUltimateConsignee($UltimateConsignee);
|
|
$Contacts->setSoldTo($SoldTo);
|
|
|
|
$InternationalForm = new InternationalFormType();
|
|
$InternationalForm->setFormType('01');
|
|
$InternationalForm->setReasonForExport('SALE');
|
|
$InternationalForm->setCurrencyCode('USD');
|
|
$InternationalForm->setContacts($Contacts);
|
|
|
|
$ShipmentServiceOptions = new ShipmentServiceOptionsType();
|
|
$ShipmentServiceOptions->setInternationalForms($InternationalForm);
|
|
|
|
$this->_request->Shipment->setShipmentServiceOptions($ShipmentServiceOptions);
|
|
}
|
|
}
|
|
|
|
public function setInvoice($date = null, $number = '') {
|
|
$this->initForms();
|
|
|
|
if ($date == null)
|
|
$date = date('Ymd');
|
|
else if (is_string($date))
|
|
$date = date('Ymd', strtotime($date));
|
|
else
|
|
$date = date('Ymd', $date);
|
|
|
|
|
|
$InternationalForm = new InternationalFormType();
|
|
$InternationalForm->setFormType('01');
|
|
|
|
$ShipmentServiceOptions = new ShipmentServiceOptionsType();
|
|
$ShipmentServiceOptions->setInternationalForms($InternationalForm);
|
|
|
|
$this->_request->Shipment
|
|
->ShipmentServiceOptions
|
|
->InternationalForms
|
|
->setInvoiceDate($date);
|
|
$this->_request->Shipment
|
|
->ShipmentServiceOptions
|
|
->InternationalForms
|
|
->setInvoiceNumber($number);
|
|
}
|
|
|
|
public function useNegotiatedRates() {
|
|
$rateInfo = new RateInfoType();
|
|
$rateInfo->setNegotiatedRatesIndicator(true);
|
|
$this->_request->Shipment->setShipmentRatingOptions($rateInfo);
|
|
}
|
|
|
|
private function setTotal() {
|
|
if ($this->_destination == 'CA') {
|
|
$invoiceLineTotal = new CurrencyMonetaryType();
|
|
$invoiceLineTotal->setCurrencyCode('USD');
|
|
$invoiceLineTotal->setMonetaryValue(ceil($this->_totalValue));
|
|
$this->_request->Shipment->setInvoiceLineTotal($invoiceLineTotal);
|
|
}
|
|
}
|
|
|
|
public function ship() {
|
|
|
|
$this->_request->Request->setRequestOption('validate');
|
|
|
|
$this->initForms();
|
|
|
|
$this->_request->Shipment->setService($this->_serviceType);
|
|
$this->_request->Shipment->setDescription('Electronics');
|
|
$this->_request->Shipment->setShipper($this->_shipper);
|
|
$this->_request->Shipment->setShipFrom($this->_shipFrom);
|
|
$this->_request->Shipment->setShipTo($this->_shipTo);
|
|
$this->_request->Shipment->setPackage($this->_packages);
|
|
$this->_request->Shipment->setPaymentInformation($this->_payment);
|
|
$this->_request->Shipment
|
|
->ShipmentServiceOptions
|
|
->InternationalForms
|
|
->setProduct($this->_products);
|
|
|
|
$this->setTotal();
|
|
|
|
$UsernameToken = new UsernameToken();
|
|
$ServiceAccessToken = new ServiceAccessToken();
|
|
$UPSSecurity = new UPSSecurity($UsernameToken, $ServiceAccessToken);
|
|
|
|
$UsernameToken->setUsername(UPS_USERID);
|
|
$UsernameToken->setPassword(UPS_USERPASS);
|
|
|
|
$ServiceAccessToken->setAccessLicenseNumber(UPS_APIKEY);
|
|
|
|
$header = new SoapHeader($this->_schema, 'UPSSecurity', $UPSSecurity);
|
|
|
|
$this->_options = [
|
|
'soap_version' => 'SOAP_1_1',
|
|
'exceptions' => true,
|
|
'trace' => true,
|
|
'location' => UPS_SHIP_SERVER
|
|
];
|
|
|
|
$wsdl = $this->_wsdl;
|
|
|
|
$this->_client = new SoapClient($wsdl, $this->_options);
|
|
$this->_client->__setSoapHeaders($header);
|
|
|
|
try {
|
|
$this->_response = $this->_client->ProcessShipment($this->_request, $this->_options);
|
|
} catch (SoapFault $s) {
|
|
if (isset($s->detail)) {
|
|
$err = $s->detail->Errors->ErrorDetail->PrimaryErrorCode->Description;
|
|
throw new Exception($err);
|
|
}
|
|
}
|
|
}
|
|
|
|
public function setLabelFormat($formatCode = 'ZPL') {
|
|
// This is _required_, with these specific values, but has no effect
|
|
$LabelStockSize = new LabelStockSizeType('6', '4');
|
|
$LabelImageFormat = new LabelImageFormatType($formatCode);
|
|
|
|
$this->_request->LabelSpecification->setLabelImageFormat($LabelImageFormat);
|
|
$this->_request->LabelSpecification->setLabelStockSize($LabelStockSize);
|
|
}
|
|
|
|
public function getLabelImage() {
|
|
if ($this->_response) {
|
|
$img = $this->_response->ShipmentResults->PackageResults->ShippingLabel->GraphicImage;
|
|
return base64_decode($img);
|
|
}
|
|
}
|
|
|
|
public function getTrackingNumber() {
|
|
if ($this->_response)
|
|
return $this->_response->ShipmentResults->PackageResults->TrackingNumber;
|
|
}
|
|
|
|
public function getCharge() {
|
|
if ($this->_response)
|
|
return $this->_response->ShipmentResults->PackageResults->ServiceOptionsCharges->MonetaryValue;
|
|
}
|
|
|
|
public function getInvoice() {
|
|
if ($this->_response) {
|
|
$img = $this->_response->ShipmentResults->Form->Image->GraphicImage;
|
|
return base64_decode($img);
|
|
}
|
|
}
|
|
|
|
public function getLastRequest() {
|
|
$request = $this->_client->__getLastRequest();
|
|
|
|
if ($request) {
|
|
$dom = new DOMDocument;
|
|
$dom->preserveWhiteSpace = FALSE;
|
|
$dom->formatOutput = TRUE;
|
|
$dom->loadXML($request);
|
|
return $dom->saveXml();
|
|
}
|
|
}
|
|
|
|
public function getLastResponse() {
|
|
$response = $this->_client->__getLastResponse();
|
|
|
|
if ($response) {
|
|
$dom = new DOMDocument;
|
|
$dom->preserveWhiteSpace = FALSE;
|
|
$dom->formatOutput = TRUE;
|
|
$dom->loadXML($response);
|
|
return $dom->saveXml();
|
|
}
|
|
}
|
|
|
|
}
|