Skip to content

Commit

Permalink
resolve external schema location relative to file
Browse files Browse the repository at this point in the history
  • Loading branch information
mringler committed Apr 8, 2021
1 parent d0d4214 commit ac9e427
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 8 deletions.
19 changes: 11 additions & 8 deletions src/Propel/Generator/Manager/AbstractManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ protected function loadDataModels()
*
* @throws \Propel\Generator\Exception\BuildException
*
* @return int
* @return int number of included external schemas
*/
protected function includeExternalSchemas(DOMDocument $dom, $srcDir)
{
Expand All @@ -395,21 +395,24 @@ protected function includeExternalSchemas(DOMDocument $dom, $srcDir)

$nbIncludedSchemas = 0;
while ($externalSchema = $externalSchemaNodes->item(0)) {
$include = $externalSchema->getAttribute('filename');
$filePath = $externalSchema->getAttribute('filename');
$referenceOnly = $externalSchema->getAttribute('referenceOnly');
$this->log('Processing external schema: ' . $include);
$this->log('Processing external schema: ' . $filePath);

$externalSchema->parentNode->removeChild($externalSchema);

if (!is_readable($include)) {
throw new BuildException("External schema '$include' does not exist");
$externalSchemaPath = realpath($srcDir . DIRECTORY_SEPARATOR . $filePath);
if ($externalSchemaPath === false) {
$externalSchemaPath = realpath($filePath);
}
if ($externalSchemaPath === false || !is_readable($externalSchemaPath)) {
throw new BuildException("Cannot read external schema at '$filePath'");
}

$externalSchemaDom = new DOMDocument('1.0', 'UTF-8');
$externalSchemaDom->load(realpath($include));
$externalSchemaDom->load($externalSchemaPath);

// The external schema may have external schemas of its own ; recurs
$this->includeExternalSchemas($externalSchemaDom, $srcDir);
$this->includeExternalSchemas($externalSchemaDom, dirname($externalSchemaPath));
foreach ($externalSchemaDom->getElementsByTagName('table') as $tableNode) {
if ($referenceOnly === 'true') {
$tableNode->setAttribute('skipSql', 'true');
Expand Down
90 changes: 90 additions & 0 deletions tests/Propel/Tests/Generator/Manager/AbstractManagerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php

/**
* MIT License. This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Propel\Tests\Generator\Manager;

use DOMDocument;
use Propel\Generator\Exception\BuildException;
use Propel\Generator\Manager\AbstractManager;
use Propel\Tests\TestCase;

/**
* @group database
*/
class AbstractManagerTest extends TestCase
{
private $manager;

/**
* @return void
*/
public function setUp(): void
{
parent::setUp();
$this->manager = new Manager();
}

/**
* @return void
*/
public function testIncludeExternalSchemaWithRelativePathTo()
{
// include book.schema.xml, which includes external author schema
$schemaXml = <<< EOT
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<database package="core.book" name="bookstore" defaultIdMethod="native" namespace="Propel\Tests\BookstorePackaged">
<external-schema filename="../../../../Fixtures/bookstore-packaged/book.schema.xml" referenceOnly="true"/>
</database>
EOT;

$dom = new DOMDocument('1.0', 'UTF-8');
$dom->loadXML($schemaXml);
$numberOfIncludedSchemas = $this->manager->callIncludeExternalSchemas($dom, __DIR__);
$this->assertEquals(1, $numberOfIncludedSchemas);

$definedTables = $dom->getElementsByTagName('table');
$this->assertEquals(2, $definedTables->length);
$expectedTablesInOrder = ['book', 'author'];
foreach ($expectedTablesInOrder as $index => $expectedTableName) {
$table = $definedTables->item($index);
$tableName = $table->getAttribute('name');
$this->assertEquals($expectedTableName, $tableName);
$skipSql = $table->getAttribute('skipSql');
$this->assertEquals('true', $skipSql);
}
}

/**
* @return void
*/
public function testIncludeExternalSchemaThrowsExceptionForMissingFiles()
{
// include book.schema.xml, which includes external author schema
$schemaXml = <<< EOT
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<database package="core.book" name="bookstore" defaultIdMethod="native" namespace="Propel\Tests\BookstorePackaged">
<external-schema filename="../ThisFileNameDoesNotExistBababuiBababui/book.schema.xml" referenceOnly="true"/>
</database>
EOT;

$dom = new DOMDocument('1.0', 'UTF-8');
$dom->loadXML($schemaXml);
$this->expectException(BuildException::class);
$this->manager->callIncludeExternalSchemas($dom, __DIR__);
}
}

class Manager extends AbstractManager
{
public function callIncludeExternalSchemas(DOMDocument $dom, $srcDir)
{
return $this->includeExternalSchemas($dom, $srcDir);
}
}

0 comments on commit ac9e427

Please sign in to comment.