Skip to content

Instantly share code, notes, and snippets.

@alan-morey
Created November 1, 2012 16:27
Show Gist options
  • Save alan-morey/3994849 to your computer and use it in GitHub Desktop.
Save alan-morey/3994849 to your computer and use it in GitHub Desktop.
PHP classes to parse result files from the Force.com Mirgration Tool "describeMetadata" and "listMetadata" ant tasks.
<?php
class DescribeMetadataResultFileParser {
const BOUNDARY = '************************************************************';
const XML_NAME_MARKER = 'XMLName: ';
const DIR_NAME_MARKER = 'DirName: ';
const SUFFIX_MARKER = 'Suffix: ';
const HAS_META_FILE_MARKER = 'HasMetaFile: ';
const IN_FOLDER_MARKER = 'InFolder: ';
const CHILD_OBJECTS_MARKER = 'ChildObjects: ';
private $resultFilePath;
private $currentResult = null;
private $results;
private $isProcessingEntry;
function __construct($resultFilePath) {
$this->resultFilePath = $resultFilePath;
}
function getResults() {
if (!is_array($this->results)) {
$this->parseLog();
}
return $this->results;
}
function parseLog() {
$fileLines = new SplFileObject($this->resultFilePath);
$this->results = array();
$this->isProcessingEntry = false;
foreach ($fileLines as $line) {
$line = trim($line);
if ($this->isProcessingEntry) {
$this->parseLine($line);
} else if ($this->isBoundary($line)) {
$this->startProcessingEntry();
}
}
$this->sortEntriesByXmlName();
}
private function startProcessingEntry() {
$this->currentResult = new DescribeMetadataResult();
$this->isProcessingEntry = true;
}
private function finishProcessingEntry() {
$this->results[] = $this->currentResult;
$this->isProcessingEntry = false;
}
private function isBoundary($line) {
return $this->lineHasMarker($line, self::BOUNDARY);
}
private function parseLine($line) {
if ($this->lineHasMarker($line, self::XML_NAME_MARKER)) {
$this->parseXmlNameLine($line);
} else if ($this->lineHasMarker($line, self::DIR_NAME_MARKER)) {
$this->parseDirNameLine($line);
} else if ($this->lineHasMarker($line, self::SUFFIX_MARKER)) {
$this->parseSuffixLine($line);
} else if ($this->lineHasMarker($line, self::HAS_META_FILE_MARKER)) {
$this->parseHasMetaFileLine($line);
} else if ($this->lineHasMarker($line, self::IN_FOLDER_MARKER)) {
$this->parseInFolderLine($line);
} else if ($this->lineHasMarker($line, self::CHILD_OBJECTS_MARKER)) {
$this->parseChildObjectsLine($line);
} else {
echo '**WARNING** line unsupported: ' . $line . "\n";
}
}
private function lineHasMarker($line, $marker) {
return strncmp($line, $marker, strlen($marker)) === 0;
}
private function parseXmlNameLine($line) {
list(, $xmlName) = explode(self::XML_NAME_MARKER, $line, 2);
$this->currentResult->xmlName = $xmlName;
}
private function parseDirNameLine($line) {
list(, $dirName) = explode(self::DIR_NAME_MARKER, $line, 2);
$this->currentResult->dirName = $dirName;
}
private function parseSuffixLine($line) {
list(, $suffix) = explode(self::SUFFIX_MARKER, $line, 2);
$this->currentResult->suffix = $suffix;
}
private function parseHasMetaFileLine($line) {
list(, $hasMetaFile) = explode(self::HAS_META_FILE_MARKER, $line, 2);
$this->currentResult->hasMetaFile = $hasMetaFile === 'true';
}
private function parseInFolderLine($line) {
list(, $inFolder) = explode(self::IN_FOLDER_MARKER, $line, 2);
$this->currentResult->inFolder = $inFolder === 'true';
}
private function parseChildObjectsLine($line) {
list(, $childObjects) = explode(self::CHILD_OBJECTS_MARKER, $line, 2);
$children = explode(',', $childObjects);
$boundary = array_pop($children);
$this->currentResult->childObjects = $children;
if ($this->isBoundary($boundary)) {
$this->finishProcessingEntry();
} else {
echo '**WARNING** Missing closing boundary for entry';
}
}
private function sortEntriesByXmlName() {
usort($this->results, function($a, $b) {
return $a->xmlName > $b->xmlName ? 1 : -1;
});
}
}
class DescribeMetadataResult {
public $xmlName;
public $dirName;
public $suffix;
public $hasMetaFile;
public $inFolder;
public $childObjects;
}
<?php
class ListMetadataResultFileParser {
const BOUNDARY = '************************************************************';
const FILENAME_MARKER = 'FileName:';
const FULLNAME_MARKER = 'FullName/Id:';
const MANAGEABLE_STATE_MARKER = 'Manageable State:';
const NAMESPACE_PREFIX_MARKER = 'Namespace Prefix:';
const CREATED_BY_MARKER = 'Created By (Name/Id):';
const LAST_MODIFIED_BY_MARKER = 'Last Modified By (Name/Id):';
const TYPE_MARKER = 'Type:';
private $resultFilePath;
private $currentResult = null;
private $results;
private $isProcessingResult;
function __construct($resultFilePath) {
$this->resultFilePath = $resultFilePath;
}
function parseLog() {
$fileLines = new SplFileObject($this->resultFilePath);
$this->results = array();
$this->isProcessingResult = false;
foreach ($fileLines as $line) {
$line = trim($line);
if ($this->isBoundary($line)) {
if (!$this->isProcessingResult) {
$this->startProcessingResult();
} else {
$this->finishProcessingResult();
}
continue;
}
if ($this->isProcessingResult) {
$this->parseLine($line);
}
}
$this->sortEntriesByFullName();
}
private function startProcessingResult() {
$this->currentResult = new ListMetadataResult();
$this->isProcessingResult = true;
}
private function finishProcessingResult() {
$this->results[] = $this->currentResult;
$this->isProcessingResult = false;
}
private function sortEntriesByFullName() {
usort($this->results, function($a, $b) {
return $a->fullName > $b->fullName ? 1 : -1;
});
}
function getResults() {
if (!is_array($this->results)) {
$this->parseLog();
}
return $this->results;
}
private function isBoundary($line) {
return $this->lineHasMarker($line, self::BOUNDARY);
}
private function parseLine($line) {
if ($this->lineHasMarker($line, self::FILENAME_MARKER)) {
$this->parseFileNameLine($line);
} else if ($this->lineHasMarker($line, self::FULLNAME_MARKER)) {
$this->parseFullNameLine($line);
} else if ($this->lineHasMarker($line, self::MANAGEABLE_STATE_MARKER)) {
$this->parseManageableStateLine($line);
} else if ($this->lineHasMarker($line, self::NAMESPACE_PREFIX_MARKER)) {
$this->parseNamespacePrefixLine($line);
} else if ($this->lineHasMarker($line, self::CREATED_BY_MARKER)) {
$this->parseCreatedByLine($line);
} else if ($this->lineHasMarker($line, self::LAST_MODIFIED_BY_MARKER)) {
$this->parseLastModifiedByLine($line);
} else if ($this->lineHasMarker($line, self::TYPE_MARKER)) {
$this->parseFileNameLine($line);
} else {
echo '**WARNING** line unsupported: >>' . $line . '<<' . "\n";
}
}
private function lineHasMarker($line, $marker) {
return strncmp($line, $marker, strlen($marker)) === 0;
}
private function parseFileNameLine($line) {
list(, $fileName) = explode(self::FILENAME_MARKER, $line, 2);
$this->currentResult->fileName = trim($fileName);
}
private function parseFullNameLine($line) {
list(, $value) = explode(self::FULLNAME_MARKER, $line, 2);
list($fullName, $id) = explode('/', trim($value), 2);
$this->currentResult->fullName = $fullName;
$this->currentResult->id = $id;
}
private function parseManageableStateLine($line) {
list(, $manageableState) = explode(self::MANAGEABLE_STATE_MARKER, $line, 2);
$this->currentResult->manageableState = trim($manageableState);
}
private function parseNamespacePrefixLine($line) {
list(, $namespacePrefix) = explode(self::NAMESPACE_PREFIX_MARKER, $line, 2);
if ($namespacePrefix === 'null') {
$namespacePrefix = null;
}
$this->currentResult->namespacePrefix = trim($namespacePrefix);
}
private function parseCreatedByLine($line) {
list(, $value) = explode(self::CREATED_BY_MARKER, $line, 2);
list($createdByName, $createdById) = explode('/', trim($value), 2);
$this->currentResult->createdByName = $createdByName;
$this->currentResult->createdById = $createdById;
}
private function parseLastModifiedByLine($line) {
list(, $value) = explode(self::LAST_MODIFIED_BY_MARKER, $line, 2);
list($lastModifiedByName, $lastModifiedById) = explode('/', trim($value), 2);
$this->currentResult->lastModifiedByName = $lastModifiedByName;
$this->currentResult->lastModifiedById = $lastModifiedById;
}
private function parseTypeLine($line) {
list(, $type) = explode(self::TYPE_MARKER, $line, 2);
$this->currentResult->type = trim($type);
}
}
class ListMetadataResult {
public $createdById;
public $createdByName;
public $fileName;
public $fullName;
public $id;
public $lastModifiedById;
public $lastModifiedByName;
public $lastModifiedByDate;
public $manageableState;
public $namespacePrefix;
public $type;
public function isManageableStateUnmanaged() {
return $this->manageableState === 'unmanaged';
}
public function isManageableStateInstalled() {
return $this->manageableState === 'installed';
}
public function hasNamespacePrefix() {
return isset($this->namespacePrefix);
}
}
class CustomFieldName {
private $fullFieldName;
private $fullObjectName;
private $objectNamespacePrefix;
private $objectName;
private $objectCustomSuffix;
private $fieldName;
function __construct($fullFieldName) {
$this->fullFieldName = $fullFieldName;
list($this->fullObjectName, $this->fieldName) = explode('.', $fullFieldName, 2);
$objNameParts = explode('__', $this->fullObjectName, 3);
$numParts = count($objNameParts);
switch ($numParts) {
case 1:
list($this->objectName) = $objNameParts;
break;
case 2:
list($this->objectName, $this->objectCustomSuffix) = $objNameParts;
break;
case 3:
list($this->objectNamespacePrefix, $this->objectName, $this->objectCustomSuffix) = $objNameParts;
break;
}
}
function getFullFieldName() {
return $this->fullFieldName;
}
function getFullObjectName() {
return $this->fullObjectName;
}
function getObjectNamespacePrefix() {
return $this->objectNamespacePrefix;
}
function hasObjectNamespacePrefix() {
return isset($this->objectNamespacePrefix);
}
function getObjectName() {
return $this->objectName;
}
function isObjectCustom() {
return isset($this->objectCustomSuffix);
}
function isObjectStandard() {
return !$this->isObjectCustom();
}
function getFieldName() {
return $this->fieldName;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment