1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360: 361:
<?php
namespace Net\Bazzline\Component\Locator\Configuration\Assembler;
use Net\Bazzline\Component\Locator\Configuration\Configuration;
use Net\Bazzline\Component\Locator\Configuration\Validator\ReadableFilePath;
use XMLReader;
class FromPropelSchemaXmlAssembler extends AbstractAssembler
{
protected function map($data, Configuration $configuration)
{
$columnClassMethodBodyBuilder =
(isset($data['column_class_method_body_builder']))
? $data['column_class_method_body_builder']
: null;
$locatorNamespace =
(isset($data['namespace']))
? $data['namespace']
: '';
$methodNameWithoutNamespace =
(isset($data['method_name_without_namespace']))
? $data['method_name_without_namespace']
: false;
$pathToSchemaXml = realpath($data['path_to_schema_xml']);
$queryClassMethodBodyBuilder =
(isset($data['query_class_method_body_builder']))
? $data['query_class_method_body_builder']
: null;
$validator = new ReadableFilePath();
$validator->validate($pathToSchemaXml);
$configuration = $this->mapBooleanProperties(
$data,
$configuration
);
$configuration = $this->mapStringProperties(
$data,
$configuration
);
$configuration = $this->mapSchemaXmlPropertiesToConfiguration(
$pathToSchemaXml,
$configuration,
$columnClassMethodBodyBuilder,
$locatorNamespace,
$queryClassMethodBodyBuilder,
$methodNameWithoutNamespace
);
$configuration = $this->mapArrayPropertiesToConfiguration(
$data,
$configuration
);
return $configuration;
}
protected function validateData($data)
{
if (!is_array($data)) {
throw new InvalidArgumentException(
'data must be an array'
);
}
if (empty($data)) {
throw new InvalidArgumentException(
'data array must contain content'
);
}
$mandatoryKeysToExpectedValueTyp = array(
'class_name' => 'string',
'file_path' => 'string'
);
$this->validateDataWithMandatoryKeysAndExpectedValueType(
$data,
$mandatoryKeysToExpectedValueTyp
);
$optionalKeysToExpectedValueTyp = array(
'extends' => 'string',
'implements' => 'array',
'method_name_without_namespace' => 'boolean',
'namespace' => 'string',
'path_to_schema_xml' => 'string',
'uses' => 'array'
);
$this->validateDataWithOptionalKeysAndExpectedValueTypeOrSetExpectedValueAsDefault(
$data,
$optionalKeysToExpectedValueTyp
);
}
private function mapSchemaXmlPropertiesToConfiguration(
$pathToSchemaXml,
Configuration $configuration,
$columnClassMethodBodyBuilder,
$locatorNamespace,
$queryClassMethodBodyBuilder,
$methodNameWithoutNamespace
)
{
$hasRootNamespace = false;
$reader = new XMLReader();
$reader->open($pathToSchemaXml);
$rootNamespace = '';
while ($reader->read()) {
if ($reader->nodeType === XMLREADER::ELEMENT) {
$nodeIsADatabase = ($reader->name === 'database');
$nodeIsATable = ($reader->name === 'table');
if ($nodeIsADatabase) {
$rootNamespace = $reader->getAttribute('namespace');
if(strlen($rootNamespace) > 0) {
$hasRootNamespace = true;
}
}
if ($nodeIsATable) {
$configuration = $this->addTableToConfiguration(
$reader,
$hasRootNamespace,
$rootNamespace,
$locatorNamespace,
$configuration,
$columnClassMethodBodyBuilder,
$queryClassMethodBodyBuilder,
$methodNameWithoutNamespace
);
}
}
}
$reader->close();
return $configuration;
}
private function mapArrayPropertiesToConfiguration(array $data, Configuration $configuration)
{
if (isset($data['implements'])) {
foreach($data['implements'] as $interfaceName) {
$configuration->addImplements($interfaceName);
}
}
if (isset($data['uses'])) {
foreach ($data['uses'] as $key => $uses) {
if (!isset($uses['class_name'])) {
throw new RuntimeException(
'use entry with key "' . $key . '" needs to have a key "class_name"'
);
}
$alias = (isset($uses['alias'])) ? $uses['alias'] : '';
$className = str_replace('\\\\', '\\', $uses['class_name']);
$configuration->addUses($className, $alias);
}
}
return $configuration;
}
private function addTableToConfiguration(
XMLReader $reader,
$hasRootNamespace,
$rootNamespace,
$locatorNamespace,
Configuration $configuration,
$columnClassMethodBodyBuilder,
$queryClassMethodBodyBuilder,
$methodNameWithoutNamespace
)
{
$namespace = $reader->getAttribute('namespace');
$phpName = $reader->getAttribute('phpName');
$tableName = $reader->getAttribute('name');
$tableNamespace = '';
$hasPhpName = (strlen($phpName) > 0);
$hasNamespace = (strlen($namespace) > 0);
if ($hasRootNamespace) {
$tableNamespace .= '\\' . $rootNamespace . '\\';
}
if ($hasNamespace) {
$tableNamespace .= $namespace . '\\';
}
$hasDifferentNamespaceThanLocator = ($locatorNamespace !== $tableNamespace);
$hasTableNamespace = (strlen($tableNamespace) > 0);
$fullQualifiedClassName = $this->createFullQualifiedClassName(
$hasPhpName,
$phpName,
$tableName,
$hasTableNamespace,
$tableNamespace
);
$classNameAlias = ($methodNameWithoutNamespace)
? $this->createClassNameAlias($hasPhpName, $phpName, $tableName)
: null;
$queryClassNameAlias =
(!is_null($classNameAlias))
? $classNameAlias . 'Query'
: null;
$fullQualifiedQueryClassName = $fullQualifiedClassName . 'Query';
$configuration->addInstance(
$fullQualifiedClassName,
false,
false,
$fullQualifiedClassName,
$classNameAlias,
$columnClassMethodBodyBuilder
);
$configuration->addInstance(
$fullQualifiedQueryClassName,
false,
false,
$fullQualifiedClassName,
$queryClassNameAlias,
$queryClassMethodBodyBuilder
);
if ($hasDifferentNamespaceThanLocator) {
$useClassName = ($this->startsWith($fullQualifiedClassName, '\\'))
? substr($fullQualifiedClassName, 1)
: $fullQualifiedClassName;
$useQueryClassName = ($this->startsWith($fullQualifiedQueryClassName, '\\'))
? substr($fullQualifiedQueryClassName, 1)
: $fullQualifiedQueryClassName;
$configuration->addUses($useClassName);
$configuration->addUses($useQueryClassName);
}
return $configuration;
}
private function startsWith($haystack, $needle)
{
return (strncmp($haystack, $needle, strlen($needle)) === 0);
}
private function createFullQualifiedClassName($hasPhpName, $phpName, $tableName, $hasTableNamespace, $tableNamespace)
{
$fullQualifiedClassName = '';
if ($hasPhpName) {
$fullQualifiedClassName = $phpName;
} else {
$tableNameAsArray = explode('_', $tableName);
array_walk($tableNameAsArray, function (&$value) {
$value = ucfirst($value);
});
$fullQualifiedClassName .= implode('', $tableNameAsArray);
}
if ($hasTableNamespace) {
$fullQualifiedClassName = $tableNamespace . '\\' . $fullQualifiedClassName;
}
$fullQualifiedClassName = str_replace('\\\\', '\\', $fullQualifiedClassName);
return $fullQualifiedClassName;
}
private function createClassNameAlias($hasPhpName, $phpName, $tableName)
{
return ($hasPhpName) ? $phpName : $tableName;
}
}