forked from ddeboer/DdeboerSalesforceMapperBundle
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from comsave/wsdlvalidator
retrieved new files
- Loading branch information
Showing
9 changed files
with
597 additions
and
0 deletions.
There are no files selected for viewing
159 changes: 159 additions & 0 deletions
159
src/LogicItLab/Salesforce/MapperBundle/WsdlValidator.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
<?php | ||
|
||
namespace LogicItLab\Salesforce\MapperBundle; | ||
|
||
use LogicItLab\Salesforce\MapperBundle\Annotation\AnnotationReader; | ||
use Symfony\Component\Finder\Finder; | ||
|
||
class WsdlValidator | ||
{ | ||
/** @var AnnotationReader */ | ||
private $annotationReader; | ||
|
||
/** @var string|string[] */ | ||
private $modelDirPath; | ||
|
||
/** @var string */ | ||
private $wsdlPath; | ||
|
||
/** @var string */ | ||
private $wsdlContents; | ||
|
||
/** | ||
* @param AnnotationReader $annotationReader | ||
* @codeCoverageIgnore | ||
*/ | ||
public function __construct(AnnotationReader $annotationReader) | ||
{ | ||
$this->annotationReader = $annotationReader; | ||
} | ||
|
||
/** | ||
* @param string|string[] $modelDirPath | ||
* @param string $wsdlPath | ||
* @return array | ||
*/ | ||
public function validate($modelDirPath, string $wsdlPath): array | ||
{ | ||
$this->modelDirPath = $modelDirPath; | ||
$this->wsdlPath = $wsdlPath; | ||
$missingFields = []; | ||
|
||
foreach ($this->getAllClassAnnotations() as $annotation) { | ||
$objectName = $annotation['object']->name; | ||
$fieldNames = $this->getFieldNames($annotation['fields']); | ||
|
||
if (!$objectName || !$fieldNames) { | ||
continue; | ||
} | ||
|
||
foreach ($fieldNames as $fieldName) { | ||
if ($this->hasField($objectName, $fieldName) === false) { | ||
$missingFields[$objectName][] = $fieldName; | ||
} | ||
} | ||
} | ||
|
||
return $missingFields; | ||
} | ||
|
||
private function getObject(string $objectName): ?string | ||
{ | ||
preg_match("/<complexType name=\"$objectName\">([\w\W]*)<\/complexType>/", $this->getWsdlContents(), $matches); | ||
|
||
return $matches[0] ?? null; | ||
} | ||
|
||
private function hasField(string $objectName, string $fieldName): bool | ||
{ | ||
return strpos($this->getObject($objectName), sprintf('<element name="%s"', $fieldName)) !== false; | ||
} | ||
|
||
private function getWsdlContents(): string | ||
{ | ||
if (!$this->wsdlContents) { | ||
$this->wsdlContents = file_get_contents($this->wsdlPath); | ||
} | ||
|
||
return $this->wsdlContents; | ||
} | ||
|
||
private function getAllClassAnnotations(): array | ||
{ | ||
return array_map(function ($className) { | ||
return $this->annotationReader->getSalesforceProperties($className); | ||
}, $this->getAllClassNames()); | ||
} | ||
|
||
private function getAllClassNames(): array | ||
{ | ||
$classNames = []; | ||
$allFiles = Finder::create()->files()->in($this->modelDirPath)->name('*.php'); | ||
foreach ($allFiles as $file) { | ||
$namespace = $this->getNamespaceFromFile($file); | ||
$className = $this->getClassNameFromFile($file); | ||
|
||
$classNames[] = "$namespace\\$className"; | ||
} | ||
|
||
return $this->filterNonExistentClasses($classNames); | ||
} | ||
|
||
private function getNamespaceFromFile(\SplFileInfo $file): ?string | ||
{ | ||
$fileText = file_get_contents($file->getRealPath()); | ||
|
||
if (preg_match('#^namespace\s+(.+?);$#sm', $fileText, $matches)) { | ||
return str_replace('/', '\\', $matches[1]); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
private function getClassNameFromFile(\SplFileInfo $file): string | ||
{ | ||
return str_replace('.php', '', $file->getFileName()); | ||
} | ||
|
||
private function filterNonExistentClasses(array $classNames): array | ||
{ | ||
$classNames = array_filter($classNames, function ($className) { | ||
return class_exists($className); | ||
}); | ||
|
||
return $classNames; | ||
} | ||
|
||
private function getFieldNames(?array $mapFieldAnnotation): ?array | ||
{ | ||
if (!$mapFieldAnnotation) { | ||
return null; | ||
} | ||
|
||
$fieldNames = []; | ||
foreach ($mapFieldAnnotation as $propertyName => $annotation) { | ||
$fieldNames[] = $annotation->name; | ||
} | ||
|
||
return $fieldNames; | ||
} | ||
|
||
private function sortByObjectName(array $missingFields): array | ||
{ | ||
ksort($missingFields); | ||
|
||
return $missingFields; | ||
} | ||
|
||
public function buildErrorMessage(array $missingFields): string | ||
{ | ||
$list = "These objects or fields are missing in wsdl:"; | ||
foreach ($this->sortByObjectName($missingFields) as $objectName => $fields) { | ||
foreach ($fields as $field) { | ||
$list .= "\n$objectName -> $field"; | ||
} | ||
} | ||
|
||
return $list; | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
src/LogicItLab/Salesforce/MapperBundle/WsdlValidatorTestCase.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<?php | ||
|
||
namespace LogicItLab\Salesforce\MapperBundle; | ||
|
||
use LogicItLab\Salesforce\MapperBundle\Annotation\AnnotationReader; | ||
use PHPUnit\Framework\TestCase; | ||
|
||
abstract class WsdlValidatorTestCase extends TestCase | ||
{ | ||
public abstract function modelAndWsdlDataProvider(): array; | ||
|
||
/** | ||
* @param $modelsDir | ||
* @param $wsdlPath | ||
* @dataProvider modelAndWsdlDataProvider | ||
*/ | ||
public function testWsdlIsValid($modelsDir, $wsdlPath) | ||
{ | ||
$missingFields = $this->buildValidator()->validate($modelsDir, $wsdlPath); | ||
|
||
$this->assertEmpty($missingFields, $this->buildValidator()->buildErrorMessage($missingFields)); | ||
} | ||
|
||
private function buildValidator(): WsdlValidator | ||
{ | ||
$annotationReader = new AnnotationReader(new \Doctrine\Common\Annotations\AnnotationReader()); | ||
|
||
return new WsdlValidator($annotationReader); | ||
} | ||
} |
117 changes: 117 additions & 0 deletions
117
tests/LogicItLab/Salesforce/MapperBundle/Resources/test.full.wsdl.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!-- | ||
Salesforce.com Enterprise Web Services API Version 48.0 | ||
Generated on 2020-03-04 12:39:40 +0000. | ||
Package Versions: | ||
Rollup Helper (Version: 13.2, Namespace: rh2) | ||
DashboardPal (Version: 1.1, Namespace: dashboard_pal) | ||
Salesforce and Chatter Apps (Version: 1.19, Namespace: sf_chttr_apps) | ||
Salesforce Connected Apps (Version: 1.7, Namespace: sf_com_apps) | ||
Mailchimp Integration App (Version: 1.73, Namespace: mc4sf) | ||
Desk.com: All-in-one Customer Support System (Version: 2.8, Namespace: deskcom) | ||
Salesforce Communities Management (for Communities with Chatter) (Version: 5.1, Namespace: ca_collab_2_0) | ||
DocuSign eSignature for Salesforce (Version: 6.3, Namespace: dsfs) | ||
Copyright 1999-2020 salesforce.com, inc. | ||
All Rights Reserved | ||
--> | ||
|
||
<definitions targetNamespace="urn:enterprise.soap.sforce.com" | ||
xmlns="http://schemas.xmlsoap.org/wsdl/" | ||
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" | ||
xmlns:xsd="http://www.w3.org/2001/XMLSchema" | ||
xmlns:tns="urn:enterprise.soap.sforce.com" | ||
xmlns:fns="urn:fault.enterprise.soap.sforce.com" | ||
xmlns:ens="urn:sobject.enterprise.soap.sforce.com"> | ||
<types> | ||
|
||
<schema elementFormDefault="qualified" xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:sobject.enterprise.soap.sforce.com"> | ||
|
||
<import namespace="urn:enterprise.soap.sforce.com"/> | ||
|
||
<!-- Base sObject (abstract) --> | ||
<complexType name="sObject"> | ||
<sequence> | ||
<element name="fieldsToNull" type="xsd:string" nillable="true" minOccurs="0" maxOccurs="unbounded"/> | ||
<element name="Id" type="tns:ID" nillable="true" /> | ||
</sequence> | ||
</complexType> | ||
|
||
<complexType name="AIRecordInsight"> | ||
<complexContent> | ||
<extension base="ens:sObject"> | ||
<sequence> | ||
<element name="AIInsightActions" nillable="true" minOccurs="0" type="tns:QueryResult"/> | ||
<element name="AIInsightFeedbacks" nillable="true" minOccurs="0" type="tns:QueryResult"/> | ||
<element name="AIInsightValues" nillable="true" minOccurs="0" type="tns:QueryResult"/> | ||
<element name="Confidence" nillable="true" minOccurs="0" type="xsd:double"/> | ||
<element name="CreatedBy" nillable="true" minOccurs="0" type="ens:User"/> | ||
<element name="CreatedById" nillable="true" minOccurs="0" type="tns:ID"/> | ||
<element name="CreatedDate" nillable="true" minOccurs="0" type="xsd:dateTime"/> | ||
<element name="IsDeleted" nillable="true" minOccurs="0" type="xsd:boolean"/> | ||
<element name="LastModifiedBy" nillable="true" minOccurs="0" type="ens:User"/> | ||
<element name="LastModifiedById" nillable="true" minOccurs="0" type="tns:ID"/> | ||
<element name="LastModifiedDate" nillable="true" minOccurs="0" type="xsd:dateTime"/> | ||
<element name="Name" nillable="true" minOccurs="0" type="xsd:string"/> | ||
<element name="RunGuid" nillable="true" minOccurs="0" type="xsd:string"/> | ||
<element name="RunStartTime" nillable="true" minOccurs="0" type="xsd:dateTime"/> | ||
<element name="Status" nillable="true" minOccurs="0" type="xsd:string"/> | ||
<element name="SystemModstamp" nillable="true" minOccurs="0" type="xsd:dateTime"/> | ||
<element name="Target" nillable="true" minOccurs="0" type="ens:Contract"/> | ||
<element name="TargetField" nillable="true" minOccurs="0" type="xsd:string"/> | ||
<element name="TargetId" nillable="true" minOccurs="0" type="tns:ID"/> | ||
<element name="TargetSobjectType" nillable="true" minOccurs="0" type="xsd:string"/> | ||
<element name="Type" nillable="true" minOccurs="0" type="xsd:string"/> | ||
<element name="UserRecordAccess" nillable="true" minOccurs="0" type="ens:UserRecordAccess"/> | ||
<element name="ValidUntil" nillable="true" minOccurs="0" type="xsd:dateTime"/> | ||
</sequence> | ||
</extension> | ||
</complexContent> | ||
</complexType> | ||
|
||
<complexType name="Account"> | ||
<complexContent> | ||
<extension base="ens:sObject"> | ||
<sequence> | ||
<element name="AccountNumber" nillable="true" minOccurs="0" type="xsd:string"/> | ||
<element name="BillingCity" nillable="true" minOccurs="0" type="xsd:string"/> | ||
<element name="BillingCountry" nillable="true" minOccurs="0" type="xsd:string"/> | ||
<element name="Owner" nillable="true" minOccurs="0" type="xsd:string"/> | ||
</sequence> | ||
</extension> | ||
</complexContent> | ||
</complexType> | ||
|
||
|
||
<complexType name="Contact"> | ||
<complexContent> | ||
<extension base="ens:sObject"> | ||
<sequence> | ||
<element name="AccountId" nillable="true" minOccurs="0" type="xsd:string"/> | ||
</sequence> | ||
</extension> | ||
</complexContent> | ||
</complexType> | ||
|
||
|
||
<complexType name="User"> | ||
<complexContent> | ||
<extension base="ens:sObject"> | ||
<sequence> | ||
<element name="City" nillable="true" minOccurs="0" type="xsd:string"/> | ||
<element name="Country" nillable="true" minOccurs="0" type="xsd:string"/> | ||
</sequence> | ||
</extension> | ||
</complexContent> | ||
</complexType> | ||
|
||
</types> | ||
<!-- Soap Service Endpoint --> | ||
<service name="SforceService"> | ||
<documentation>Sforce SOAP API</documentation> | ||
<port binding="tns:SoapBinding" name="Soap"> | ||
<soap:address location="https://login.salesforce.com/services/Soap/c/48.0/0DF2p000000cI92"/> | ||
</port> | ||
</service> | ||
</definitions> |
Oops, something went wrong.