initial commit

This commit is contained in:
Chris Sewell
2012-11-28 03:55:08 -05:00
parent 7adb399b2e
commit cf140a2e97
3247 changed files with 492437 additions and 0 deletions

View File

@ -0,0 +1,33 @@
<?php
/*
* $Id: EngineException.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'phing/BuildException.php';
/**
* The base class of all exceptions thrown by the engine.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Daniel Rall <dlr@collab.net> (Torque)
* @author Jason van Zyl <jvz@apache.org> (Torque)
* @version $Revision: 536 $
* @package propel.engine
*/
class EngineException extends BuildException {}

View File

@ -0,0 +1,221 @@
<?php
/*
* $Id: DataModelBuilder.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
/**
* This is the base class for any builder class that is using the data model.
*
* This could be extended by classes that build SQL DDL, PHP classes, configuration
* files, input forms, etc.
*
* This class has a static method to return the correct builder subclass identified by
* a given key. Note that in order for this factory method to work, the properties have to have
* been loaded first. Usage should look something like this (from within a AbstractProelDataModelTask subclass):
*
* <code>
* DataModelBuilder::setBuildProperties($this->getPropelProperties());
* $builder = DataModelBuilder::builderFactory($table, 'peer');
* // $builder (by default) instanceof PHP5ComplexPeerBuilder
* </code>
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder
*/
abstract class DataModelBuilder {
// --------------------------------------------------------------
// Static properties & methods
// --------------------------------------------------------------
/**
* Build properties (after they've been transformed from "propel.some.name" => "someName").
* @var array string[]
*/
private static $buildProperties = array();
/**
* Sets the [name transformed] build properties to use.
* @param array Property values keyed by [transformed] prop names.
*/
public static function setBuildProperties($props)
{
self::$buildProperties = $props;
}
/**
* Get a specific [name transformed] build property.
* @param string $name
* @return string
*/
public static function getBuildProperty($name)
{
return isset(self::$buildProperties[$name]) ? self::$buildProperties[$name] : null;
}
/**
* Imports and returns the classname of the builder class for specified 'type'.
* @param $type The "key" for class to load.
* @return string The unqualified classname.
*/
public static function getBuilderClass($type)
{
if (empty(self::$buildProperties)) {
throw new BuildException("Cannot determine builder class when no build properties have been loaded (hint: Did you call DataModelBuilder::setBuildProperties(\$props) first?)");
}
$propname = 'builder' . ucfirst(strtolower($type)) . 'Class';
$classpath = self::getBuildProperty($propname);
if (empty($classpath)) {
throw new BuildException("Unable to find class path for '$propname' property.");
}
// This is a slight hack to workaround camel case inconsistencies for the DDL classes.
// Basically, we want to turn ?.?.?.sqliteDDLBuilder into ?.?.?.SqliteDDLBuilder
$lastdotpos = strrpos($classpath, '.');
if ($lastdotpos) $classpath{$lastdotpos+1} = strtoupper($classpath{$lastdotpos+1});
else ucfirst($classpath);
return Phing::import($classpath);
}
/**
* Factory method to load a new builder instance based on specified type.
* @param Table $table
* @param $type The "key" for class to load.
* @throws BuildException if specified class cannot be found / loaded.
*/
public static function builderFactory(Table $table, $type)
{
$classname = self::getBuilderClass($type);
return new $classname($table);
}
/**
* Utility function to build a path for use in include()/require() statement.
*
* Supports two function signatures:
* (1) getFilePath($dotPathClass);
* (2) getFilePath($dotPathPrefix, $className);
*
* @param string $path dot-path to class or to package prefix.
* @param string $classname class name
* @return string
*/
public static function getFilePath($path, $classname = null, $extension = '.php')
{
$path = strtr(ltrim($path, '.'), '.', '/');
if ($classname !== null) {
if ($path !== "") { $path .= '/'; }
return $path . $classname . $extension;
} else {
return $path . $extension;
}
}
// --------------------------------------------------------------
// Non-static properties & methods inherited by subclasses
// --------------------------------------------------------------
/**
* The current table.
* @var Table
*/
private $table;
/**
* An array of warning messages that can be retrieved for display (e.g. as part of phing build process).
* @var array string[]
*/
private $warnings = array();
/**
* Creates new instance of DataModelBuilder subclass.
* @param Table $table The Table which we are using to build [OM, DDL, etc.].
*/
public function __construct(Table $table)
{
$this->table = $table;
}
/**
* Returns the Platform class for this table (database).
* @return Platform
*/
protected function getPlatform()
{
return $this->getTable()->getDatabase()->getPlatform();
}
/**
* Returns the database for current table.
* @return Database
*/
protected function getDatabase()
{
return $this->getTable()->getDatabase();
}
/**
* Returns the current Table object.
* @return Table
*/
protected function getTable()
{
return $this->table;
}
/**
* Pushes a message onto the stack of warnings.
* @param string $msg The warning message.
*/
protected function warn($msg)
{
$this->warnings[] = $msg;
}
/**
* Gets array of warning messages.
* @return array string[]
*/
public function getWarnings()
{
return $this->warnings;
}
/**
* Wraps call to Platform->quoteIdentifier() with a check to see whether quoting is enabled.
*
* All subclasses should call this quoteIdentifier() method rather than calling the Platform
* method directly. This method is used by both DataSQLBuilder and DDLBuilder, and potentially
* in the OM builders also, which is why it is defined in this class.
*
* @param string $text The text to quote.
* @return string Quoted text.
*/
public function quoteIdentifier($text)
{
if (!self::getBuildProperty('disableIdentifierQuoting')) {
return $this->getPlatform()->quoteIdentifier($text);
}
return $text;
}
}

View File

@ -0,0 +1,107 @@
<?php
/*
* $Id: ClassTools.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
/**
* Tools to support class & package inclusion and referencing.
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 536 $
* @package propel.engine.builder.om
*/
class ClassTools {
/**
* Gets just classname, given a dot-path to class.
* @param string $qualifiedName
* @return string
*/
public static function classname($qualifiedName)
{
$pos = strrpos($qualifiedName, '.');
if ($pos === false) {
return $qualifiedName; // there is no '.' in the qualifed name
} else {
return substr($qualifiedName, $pos + 1); // start just after '.'
}
}
/**
* Gets the path to be used in include()/require() statement.
*
* Supports two function signatures:
* (1) getFilePath($dotPathClass);
* (2) getFilePath($dotPathPrefix, $className);
*
* @param string $path dot-path to class or to package prefix.
* @param string $classname class name
* @return string
*/
public static function getFilePath($path, $classname = null, $extension = '.php')
{
$path = strtr(ltrim($path, '.'), '.', '/');
if ($classname !== null) {
if ($path !== "") { $path .= '/'; }
return $path . $classname . $extension;
} else {
return $path . $extension;
}
}
/**
* Gets the basePeer path if specified for table/db.
* If not, will return 'propel.util.BasePeer'
* @return string
*/
public static function getBasePeer(Table $table) {
$class = $table->getBasePeer();
if ($class === null) {
$class = "propel.util.BasePeer";
}
return $class;
}
/**
* Gets the baseClass path if specified for table/db.
* If not, will return 'propel.om.BaseObject'
* @return string
*/
public static function getBaseClass(Table $table) {
$class = $table->getBaseClass();
if ($class === null) {
$class = "propel.om.BaseObject";
}
return $class;
}
/**
* Gets the interface path if specified for table.
* If not, will return 'propel.om.Persistent'.
* @return string
*/
public static function getInterface(Table $table) {
$interface = $table->getInterface();
if ($interface === null && !$table->isReadOnly()) {
$interface = "propel.om.Persistent";
}
return $interface;
}
}

View File

@ -0,0 +1,409 @@
<?php
/*
* $Id: OMBuilder.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/DataModelBuilder.php';
/**
* Baseclass for OM-building classes.
*
* OM-building classes are those that build a PHP (or other) class to service
* a single table. This includes Peer classes, Entity classes, Map classes,
* Node classes, etc.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.om
*/
abstract class OMBuilder extends DataModelBuilder {
/**
* Peer builder class for current table.
* @var DataModelBuilder
*/
private $peerBuilder;
/**
* Stub Peer builder class for current table.
* @var DataModelBuilder
*/
private $stubPeerBuilder;
/**
* Object builder class for current table.
* @var DataModelBuilder
*/
private $objectBuilder;
/**
* Stub Object builder class for current table.
* @var DataModelBuilder
*/
private $stubObjectBuilder;
/**
* MapBuilder builder class for current table.
* @var DataModelBuilder
*/
private $mapBuilderBuilder;
/**
* Stub Interface builder class for current table.
* @var DataModelBuilder
*/
private $interfaceBuilder;
/**
* Stub child object for current table.
* @var DataModelBuilder
*/
private $multiExtendObjectBuilder;
/**
* Node object builder for current table.
* @var DataModelBuilder
*/
private $nodeBuilder;
/**
* Node peer builder for current table.
* @var DataModelBuilder
*/
private $nodePeerBuilder;
/**
* Stub node object builder for current table.
* @var DataModelBuilder
*/
private $stubNodeBuilder;
/**
* Stub node peer builder for current table.
* @var DataModelBuilder
*/
private $stubNodePeerBuilder;
/**
* Returns new or existing Peer builder class for this table.
* @return DataModelBuilder
*/
public function getPeerBuilder()
{
if (!isset($this->peerBuilder)) {
$this->peerBuilder = DataModelBuilder::builderFactory($this->getTable(), 'peer');
}
return $this->peerBuilder;
}
/**
* Returns new or existing stub Peer builder class for this table.
* @return DataModelBuilder
*/
public function getStubPeerBuilder()
{
if (!isset($this->stubPeerBuilder)) {
$this->stubPeerBuilder = DataModelBuilder::builderFactory($this->getTable(), 'peerstub');
}
return $this->stubPeerBuilder;
}
/**
* Returns new or existing Object builder class for this table.
* @return DataModelBuilder
*/
public function getObjectBuilder()
{
if (!isset($this->objectBuilder)) {
$this->objectBuilder = DataModelBuilder::builderFactory($this->getTable(), 'object');
}
return $this->objectBuilder;
}
/**
* Returns new or existing stub Object builder class for this table.
* @return DataModelBuilder
*/
public function getStubObjectBuilder()
{
if (!isset($this->stubObjectBuilder)) {
$this->stubObjectBuilder = DataModelBuilder::builderFactory($this->getTable(), 'objectstub');
}
return $this->stubObjectBuilder;
}
/**
* Returns new or existing MapBuilder builder class for this table.
* @return DataModelBuilder
*/
public function getMapBuilderBuilder()
{
if (!isset($this->mapBuilderBuilder)) {
$this->mapBuilderBuilder = DataModelBuilder::builderFactory($this->getTable(), 'mapbuilder');
}
return $this->mapBuilderBuilder;
}
/**
* Returns new or existing stub Interface builder class for this table.
* @return DataModelBuilder
*/
public function getInterfaceBuilder()
{
if (!isset($this->interfaceBuilder)) {
$this->interfaceBuilder = DataModelBuilder::builderFactory($this->getTable(), 'interface');
}
return $this->interfaceBuilder;
}
/**
* Returns new or existing stub child object builder class for this table.
* @return DataModelBuilder
*/
public function getMultiExtendObjectBuilder()
{
if (!isset($this->multiExtendObjectBuilder)) {
$this->multiExtendObjectBuilder = DataModelBuilder::builderFactory($this->getTable(), 'objectmultiextend');
}
return $this->multiExtendObjectBuilder;
}
/**
* Returns new or existing node Object builder class for this table.
* @return DataModelBuilder
*/
public function getNodeBuilder()
{
if (!isset($this->nodeBuilder)) {
$this->nodeBuilder = DataModelBuilder::builderFactory($this->getTable(), 'node');
}
return $this->nodeBuilder;
}
/**
* Returns new or existing node Peer builder class for this table.
* @return DataModelBuilder
*/
public function getNodePeerBuilder()
{
if (!isset($this->nodePeerBuilder)) {
$this->nodePeerBuilder = DataModelBuilder::builderFactory($this->getTable(), 'nodepeer');
}
return $this->nodePeerBuilder;
}
/**
* Returns new or existing stub node Object builder class for this table.
* @return DataModelBuilder
*/
public function getStubNodeBuilder()
{
if (!isset($this->stubNodeBuilder)) {
$this->stubNodeBuilder = DataModelBuilder::builderFactory($this->getTable(), 'nodestub');
}
return $this->stubNodeBuilder;
}
/**
* Returns new or existing stub node Peer builder class for this table.
* @return DataModelBuilder
*/
public function getStubNodePeerBuilder()
{
if (!isset($this->stubNodePeerBuilder)) {
$this->stubNodePeerBuilder = DataModelBuilder::builderFactory($this->getTable(), 'nodepeerstub');
}
return $this->stubNodePeerBuilder;
}
/**
* Convenience method to return a NEW Peer class builder instance.
* This is used very frequently from the peer and object builders to get
* a peer builder for a RELATED table.
* @param Table $table
* @return PeerBuilder
*/
public static function getNewPeerBuilder(Table $table)
{
return DataModelBuilder::builderFactory($table, 'peer');
}
/**
* Convenience method to return a NEW Object class builder instance.
* This is used very frequently from the peer and object builders to get
* an object builder for a RELATED table.
* @param Table $table
* @return ObjectBuilder
*/
public static function getNewObjectBuilder(Table $table)
{
return DataModelBuilder::builderFactory($table, 'object');
}
/**
* Builds the PHP source for current class and returns it as a string.
*
* This is the main entry point and defines a basic structure that classes should follow.
* In most cases this method will not need to be overridden by subclasses. This method
* does assume that the output language is PHP code, so it will need to be overridden if
* this is not the case.
*
* @return string The resulting PHP sourcecode.
*/
public function build()
{
$script = "<" . "?php\n"; // intentional concatenation
$this->addIncludes($script);
$this->addClassOpen($script);
$this->addClassBody($script);
$this->addClassClose($script);
return $script;
}
/**
* Returns the name of the current class being built.
* @return string
*/
abstract public function getClassname();
/**
* Gets the dot-path representation of current class being built.
* @return string
*/
public function getClasspath()
{
if ($this->getPackage()) {
$path = $this->getPackage() . '.' . $this->getClassname();
} else {
$path = $this->getClassname();
}
return $path;
}
/**
* Gets the full path to the file for the current class.
* @return string
*/
public function getClassFilePath()
{
return parent::getFilePath($this->getPackage(), $this->getClassname());
}
/**
* Gets package name for this table.
* This is overridden by child classes that have different packages.
* @return string
*/
public function getPackage()
{
$pkg = ($this->getTable()->getPackage() ? $this->getTable()->getPackage() : $this->getDatabase()->getPackage());
if (!$pkg) {
$pkg = $this->getBuildProperty('targetPackage');
}
return $pkg;
}
/**
* Returns filesystem path for current package.
* @return string
*/
public function getPackagePath()
{
return strtr($this->getPackage(), '.', '/');
}
/**
* Shortcut method to return the [stub] peer classname for current table.
* This is the classname that is used whenever object or peer classes want
* to invoke methods of the peer classes.
* @return string (e.g. 'MyPeer')
* @see StubPeerBuilder::getClassname()
*/
public function getPeerClassname() {
return $this->getStubPeerBuilder()->getClassname();
}
/**
* Returns the object classname for current table.
* This is the classname that is used whenever object or peer classes want
* to invoke methods of the object classes.
* @return string (e.g. 'My')
* @see StubPeerBuilder::getClassname()
*/
public function getObjectClassname() {
return $this->getStubObjectBuilder()->getClassname();
}
/**
* Get the column constant name (e.g. PeerName::COLUMN_NAME).
*
* @param Column $col The column we need a name for.
* @param string $phpName The PHP Name of the peer class. The 'Peer' is appended automatically.
*
* @return string If $phpName is provided, then will return {$phpName}Peer::COLUMN_NAME; if not, then uses current table COLUMN_NAME.
*/
public function getColumnConstant($col, $phpName = null)
{
if ($col === null) {
$e = new Exception("No col specified.");
print $e;
throw $e;
}
$classname = $this->getPeerClassname($phpName);
// was it overridden in schema.xml ?
if ($col->getPeerName()) {
$const = strtoupper($col->getPeerName());
} else {
$const = strtoupper($col->getName());
}
return $classname.'::'.$const;
}
/**
* Gets just classname, given a dot-path to class.
* @param string $qualifiedName
* @return string
*/
public function classname($qualifiedName)
{
$pos = strrpos($qualifiedName, '.');
if ($pos === false) {
return $qualifiedName; // there is no '.' in the qualifed name
} else {
return substr($qualifiedName, $pos + 1); // start just after '.'
}
}
/**
* Gets the basePeer path if specified for table/db.
* If not, will return 'propel.util.BasePeer'
* @return string
*/
public function getBasePeer(Table $table) {
$class = $table->getBasePeer();
if ($class === null) {
$class = "propel.util.BasePeer";
}
return $class;
}
}

View File

@ -0,0 +1,148 @@
<?php
/*
* $Id: ObjectBuilder.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/om/OMBuilder.php';
/**
* Base class for Peer-building classes.
*
* This class is designed so that it can be extended by a PHP4PeerBuilder in addition
* to the "standard" PHP5PeerBuilder and PHP5ComplexOMPeerBuilder. Hence, this class
* should not have any actual template code in it -- simply basic logic & utility
* methods.
*
* @author Hans Lellelid <hans@xmpl.org>
*/
abstract class ObjectBuilder extends OMBuilder {
/**
* Constructs a new PeerBuilder subclass.
*/
public function __construct(Table $table) {
parent::__construct($table);
}
/**
* This method adds the contents of the generated class to the script.
*
* This method is abstract and should be overridden by the subclasses.
*
* Hint: Override this method in your subclass if you want to reorganize or
* drastically change the contents of the generated peer class.
*
* @param string &$script The script will be modified in this method.
*/
abstract protected function addClassBody(&$script);
/**
* Adds the getter methods for the column values.
* This is here because it is probably generic enough to apply to templates being generated
* in different langauges (e.g. PHP4 and PHP5).
* @param string &$script The script will be modified in this method.
*/
protected function addColumnAccessorMethods(&$script)
{
$table = $this->getTable();
foreach ($table->getColumns() as $col) {
if ($col->getType() === PropelTypes::DATE || $col->getType() === PropelTypes::TIME || $col->getType() === PropelTypes::TIMESTAMP) {
$this->addTemporalAccessor($script, $col);
} else {
$this->addGenericAccessor($script, $col);
}
if ($col->isLazyLoad()) {
$this->addLazyLoader($script, $col);
}
}
}
/**
* Adds the mutator (setter) methods for setting column values.
* This is here because it is probably generic enough to apply to templates being generated
* in different langauges (e.g. PHP4 and PHP5).
* @param string &$script The script will be modified in this method.
*/
protected function addColumnMutatorMethods(&$script)
{
foreach ($this->getTable()->getColumns() as $col) {
if ($col->isLob()) {
$this->addLobMutator($script, $col);
} elseif ($col->getType() === PropelTypes::DATE || $col->getType() === PropelTypes::TIME || $col->getType() === PropelTypes::TIMESTAMP) {
$this->addTemporalMutator($script, $col);
} else {
$this->addDefaultMutator($script, $col);
}
}
}
/**
* Gets the baseClass path if specified for table/db.
* If not, will return 'propel.om.BaseObject'
* @return string
*/
protected function getBaseClass() {
$class = $this->getTable()->getBaseClass();
if ($class === null) {
$class = "propel.om.BaseObject";
}
return $class;
}
/**
* Gets the interface path if specified for current table.
* If not, will return 'propel.om.Persistent'.
* @return string
*/
protected function getInterface() {
$interface = $this->getTable()->getInterface();
if ($interface === null && !$this->getTable()->isReadOnly()) {
$interface = "propel.om.Persistent";
}
return $interface;
}
/**
* Whether to add the generic mutator methods (setByName(), setByPosition(), fromArray()).
* This is based on the build property propel.addGenericMutators, and also whether the
* table is read-only or an alias.
*/
protected function isAddGenericMutators()
{
$table = $this->getTable();
return (!$table->isAlias() && $this->getBuildProperty('addGenericMutators') && !$table->isReadOnly());
}
/**
* Whether to add the generic accessor methods (getByName(), getByPosition(), toArray()).
* This is based on the build property propel.addGenericAccessors, and also whether the
* table is an alias.
*/
protected function isAddGenericAccessors()
{
$table = $this->getTable();
return (!$table->isAlias() && $this->getBuildProperty('addGenericAccessors'));
}
}

View File

@ -0,0 +1,269 @@
<?php
/*
* $Id: PeerBuilder.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/om/OMBuilder.php';
/**
* Base class for Peer-building classes.
*
* This class is designed so that it can be extended by a PHP4PeerBuilder in addition
* to the "standard" PHP5PeerBuilder and PHP5ComplexOMPeerBuilder. Hence, this class
* should not have any actual template code in it -- simply basic logic & utility
* methods.
*
* @author Hans Lellelid <hans@xmpl.org>
*/
abstract class PeerBuilder extends OMBuilder {
protected $basePeerClass;
protected $basePeerClassname;
/**
* Constructs a new PeerBuilder subclass.
*/
public function __construct(Table $table) {
parent::__construct($table);
$this->basePeerClass = $this->getBasePeer($table);
$this->basePeerClassname = $this->classname($this->basePeerClass);
}
/**
* Adds the addSelectColumns(), doCount(), etc. methods.
* @param string &$script The script will be modified in this method.
*/
protected function addSelectMethods(&$script)
{
$this->addAddSelectColumns($script);
$this->addCountConstants($script);
$this->addDoCount($script);
// consider refactoring the doSelect stuff
// into a top-level method
$this->addDoSelectOne($script);
$this->addDoSelect($script);
$this->addDoSelectRS($script); // <-- there's Creole code in here
$this->addPopulateObjects($script); // <-- there's Creole code in here
}
/**
* Adds the correct getOMClass() method, depending on whether this table uses inheritance.
* @param string &$script The script will be modified in this method.
*/
protected function addGetOMClassMethod(&$script)
{
$table = $this->getTable();
if ($table->getChildrenColumn()) {
if ($table->isAbstract()) {
$this->addGetOMClass_Inheritance_Abstract($script);
} else {
$this->addGetOMClass_Inheritance($script);
}
} else {
if ($table->isAbstract()) {
$this->addGetOMClass_NoInheritance_Abstract($script);
} else {
$this->addGetOMClass_NoInheritance($script);
}
}
}
/**
* Adds the doInsert(), doUpdate(), doDeleteAll(), doValidate(), etc. methods.
* @param string &$script The script will be modified in this method.
*/
protected function addUpdateMethods(&$script)
{
$this->addDoInsert($script);
$this->addDoUpdate($script);
$this->addDoDeleteAll($script);
$this->addDoDelete($script);
if ($this->isDeleteCascadeEmulationNeeded()) {
$this->addDoOnDeleteCascade($script);
}
if ($this->isDeleteSetNullEmulationNeeded()) {
$this->addDoOnDeleteSetNull($script);
}
$this->addDoValidate($script);
}
/**
* Adds the retrieveByPK() (and possibly retrieveByPKs()) method(s) appropriate for this class.
* @param string &$script The script will be modified in this method.
*/
protected function addRetrieveByPKMethods(&$script)
{
if (count($this->getTable()->getPrimaryKey()) === 1) {
$this->addRetrieveByPK_SinglePK($script);
$this->addRetrieveByPKs_SinglePK($script);
} else {
$this->addRetrieveByPK_MultiPK($script);
}
}
/**
* This method adds the contents of the generated class to the script.
*
* This method contains the high-level logic that determines which methods
* get generated.
*
* Hint: Override this method in your subclass if you want to reorganize or
* drastically change the contents of the generated peer class.
*
* @param string &$script The script will be modified in this method.
*/
protected function addClassBody(&$script)
{
$table = $this->getTable();
if (!$table->isAlias()) {
$this->addConstantsAndAttributes($script);
}
$this->addGetMapBuilder($script);
$this->addGetPhpNameMap($script);
$this->addTranslateFieldName($script);
$this->addGetFieldNames($script);
if (!$table->isAlias()) {
$this->addAlias($script); // alias() utility method (deprecated?)
$this->addSelectMethods($script);
$this->addGetTableMap($script);
}
$this->addGetOMClassMethod($script);
// add the insert, update, delete, validate etc. methods
if (!$table->isAlias() && !$table->isReadOnly()) {
$this->addUpdateMethods($script);
}
if (count($table->getPrimaryKey()) > 0) {
$this->addRetrieveByPKMethods($script);
}
}
/**
* Whether the platform in use requires ON DELETE CASCADE emulation and whether there are references to this table.
* @return boolean
*/
protected function isDeleteCascadeEmulationNeeded()
{
$table = $this->getTable();
if ((!$this->getPlatform()->supportsNativeDeleteTrigger() || $this->getBuildProperty('emulateForeignKeyConstraints')) && count($table->getReferrers()) > 0) {
foreach ($table->getReferrers() as $fk) {
if ($fk->getOnDelete() == ForeignKey::CASCADE) {
return true;
}
}
}
return false;
}
/**
* Whether the platform in use requires ON DELETE SETNULL emulation and whether there are references to this table.
* @return boolean
*/
protected function isDeleteSetNullEmulationNeeded()
{
$table = $this->getTable();
if ((!$this->getPlatform()->supportsNativeDeleteTrigger() || $this->getBuildProperty('emulateForeignKeyConstraints')) && count($table->getReferrers()) > 0) {
foreach ($table->getReferrers() as $fk) {
if ($fk->getOnDelete() == ForeignKey::SETNULL) {
return true;
}
}
}
return false;
}
/**
* Whether to add the generic mutator methods (setByName(), setByPosition(), fromArray()).
* This is based on the build property propel.addGenericMutators, and also whether the
* table is read-only or an alias.
* @return boolean
*/
protected function isAddGenericMutators()
{
$table = $this->getTable();
return (!$table->isAlias() && $this->getBuildProperty('addGenericMutators') && !$table->isReadOnly());
}
/**
* Whether to add the generic accessor methods (getByName(), getByPosition(), toArray()).
* This is based on the build property propel.addGenericAccessors, and also whether the
* table is an alias.
* @return boolean
*/
protected function isAddGenericAccessors()
{
$table = $this->getTable();
return (!$table->isAlias() && $this->getBuildProperty('addGenericAccessors'));
}
/**
* Returns the retrieveByPK method name to use for this table.
* If the table is an alias then the method name looks like "retrieveTablenameByPK"
* otherwise simply "retrieveByPK".
* @return string
*/
public function getRetrieveMethodName()
{
if ($this->getTable()->isAlias()) {
$retrieveMethod = "retrieve" . $this->getTable()->getPhpName() . "ByPK";
} else {
$retrieveMethod = "retrieveByPK";
}
return $retrieveMethod;
}
/**
* COMPATIBILITY: Get the column constant name (e.g. PeerName::COLUMN_NAME).
*
* This method exists simply because it belonged to the 'PeerBuilder' that this
* class is replacing (because of name conflict more than actual functionality overlap).
* When the new builder model is finished this method will be removed.
*
* @param Column $col The column we need a name for.
* @param string $phpName The PHP Name of the peer class. The 'Peer' is appended automatically.
*
* @return string If $phpName is provided, then will return {$phpName}Peer::COLUMN_NAME; if not, just COLUMN_NAME.
* @deprecated
*/
public static function getColumnName(Column $col, $phpName = null) {
// was it overridden in schema.xml ?
if ($col->getPeerName()) {
$const = strtoupper($col->getPeerName());
} else {
$const = strtoupper($col->getName());
}
if ($phpName !== null) {
return $phpName . 'Peer::' . $const;
} else {
return $const;
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,866 @@
<?php
/*
* $Id: PHP5ComplexPeerBuilder.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/om/php5/PHP5BasicPeerBuilder.php';
/**
* Generates a PHP5 base Peer class with complex object model methods.
*
* This class extends the basic peer builder by adding on the doSelectJoin*()
* methods and other complex object model methods.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.om.php5
*/
class PHP5ComplexPeerBuilder extends PHP5BasicPeerBuilder {
/**
* Adds the complex OM methods to the base addSelectMethods() function.
* @param string &$script The script will be modified in this method.
* @see PeerBuilder::addSelectMethods()
*/
protected function addSelectMethods(&$script)
{
$table = $this->getTable();
parent::addSelectMethods($script);
$this->addDoCountJoin($script);
$this->addDoSelectJoin($script);
$countFK = count($table->getForeignKeys());
$includeJoinAll = true;
foreach ($this->getTable()->getForeignKeys() as $fk) {
$tblFK = $table->getDatabase()->getTable($fk->getForeignTableName());
if ($tblFK->isForReferenceOnly()) {
$includeJoinAll = false;
}
}
if ($includeJoinAll) {
if($countFK > 0) {
$this->addDoCountJoinAll($script);
$this->addDoSelectJoinAll($script);
}
if ($countFK > 1) {
$this->addDoCountJoinAllExcept($script);
$this->addDoSelectJoinAllExcept($script);
}
}
}
/**
* Adds the doSelectJoin*() methods.
* @param string &$script The script will be modified in this method.
*/
protected function addDoSelectJoin(&$script)
{
$table = $this->getTable();
$className = $table->getPhpName();
$countFK = count($table->getForeignKeys());
if ($countFK >= 1) {
foreach ($table->getForeignKeys() as $fk) {
$joinTable = $table->getDatabase()->getTable($fk->getForeignTableName());
if (!$joinTable->isForReferenceOnly()) {
// FIXME - look into removing this next condition; it may not
// be necessary:
// --- IT is necessary because there needs to be a system for
// aliasing the table if it is the same table.
if ( $fk->getForeignTableName() != $table->getName() ) {
/*
REPLACED BY USING THE ObjectBuilder objects below
// check to see if we need to add something to the method name.
// For example if there are multiple columns that reference the same
// table, then we have to have a methd name like doSelectJoinBooksByBookId
$partJoinName = "";
foreach ($fk->getLocalColumns() as $columnName ) {
$column = $table->getColumn($columnName);
// this second part is not currently ever true (right?)
if ($column->isMultipleFK() || $fk->getForeignTableName() == $table->getName()) {
$partJoinName = $partJoinName . $column->getPhpName();
}
}
$joinClassName = $joinTable->getPhpName();
if ($joinTable->getInterface()) {
$interfaceName = $joinTable->getInterface();
} else {
$interfaceName = $joinTable->getPhpName();
}
if ($partJoinName == "") {
$joinColumnId = $joinClassName;
$joinInterface = $interfaceName;
$collThisTable = $className . "s";
$collThisTableMs = $className;
} else {
$joinColumnId = $joinClassName . "RelatedBy" . $partJoinName;
$joinInterface = $interfaceName . "RelatedBy" . $partJoinName;
$collThisTable = $className . "sRelatedBy" . $partJoinName;
$collThisTableMs = $className . "RelatedBy" . $partJoinName;
}
*/
$joinClassName = $joinTable->getPhpName();
$thisTableObjectBuilder = OMBuilder::getNewObjectBuilder($table);
$joinedTableObjectBuilder = OMBuilder::getNewObjectBuilder($joinTable);
$joinedTablePeerBuilder = OMBuilder::getNewPeerBuilder($joinTable);
$script .= "
/**
* Selects a collection of $className objects pre-filled with their $joinClassName objects.
*
* @return array Array of $className objects.
* @throws PropelException Any exceptions caught during processing will be
* rethrown wrapped into a PropelException.
*/
public static function doSelectJoin".$thisTableObjectBuilder->getFKPhpNameAffix($fk, $plural = false)."(Criteria \$c, \$con = null)
{
\$c = clone \$c;
// Set the correct dbName if it has not been overridden
if (\$c->getDbName() == Propel::getDefaultDB()) {
\$c->setDbName(self::DATABASE_NAME);
}
".$this->getPeerClassname()."::addSelectColumns(\$c);
\$startcol = (".$this->getPeerClassname()."::NUM_COLUMNS - ".$this->getPeerClassname()."::NUM_LAZY_LOAD_COLUMNS) + 1;
".$joinedTablePeerBuilder->getPeerClassname()."::addSelectColumns(\$c);
";
$lfMap = $fk->getLocalForeignMapping();
foreach ($fk->getLocalColumns() as $columnName ) {
$column = $table->getColumn($columnName);
$columnFk = $joinTable->getColumn( $lfMap[$columnName] );
$script .= "
\$c->addJoin(".$this->getColumnConstant($column).", ".$joinedTablePeerBuilder->getColumnConstant($columnFk).");"; //CHECKME
}
$script .= "
\$rs = ".$this->basePeerClassname."::doSelect(\$c, \$con);
\$results = array();
while(\$rs->next()) {
";
if ($table->getChildrenColumn()) {
$script .= "
\$omClass = ".$this->getPeerClassname()."::getOMClass(\$rs, 1);
";
} else {
$script .= "
\$omClass = ".$this->getPeerClassname()."::getOMClass();
";
}
$script .= "
\$cls = Propel::import(\$omClass);
\$obj1 = new \$cls();
\$obj1->hydrate(\$rs);
";
if ($joinTable->getChildrenColumn()) {
$script .= "
\$omClass = ".$joinedTablePeerBuilder->getPeerClassname()."::getOMClass(\$rs, \$startcol);
";
} else {
$script .= "
\$omClass = ".$joinedTablePeerBuilder->getPeerClassname()."::getOMClass();
";
}
$script .= "
\$cls = Propel::import(\$omClass);
\$obj2 = new \$cls();
\$obj2->hydrate(\$rs, \$startcol);
\$newObject = true;
foreach(\$results as \$temp_obj1) {
\$temp_obj2 = \$temp_obj1->get".$thisTableObjectBuilder->getFKPhpNameAffix($fk, $plural = false)."(); //CHECKME
if (\$temp_obj2->getPrimaryKey() === \$obj2->getPrimaryKey()) {
\$newObject = false;
// e.g. \$author->addBookRelatedByBookId()
\$temp_obj2->add".$joinedTableObjectBuilder->getRefFKPhpNameAffix($fk, $plural = false)."(\$obj1); //CHECKME
break;
}
}
if (\$newObject) {
\$obj2->init".$joinedTableObjectBuilder->getRefFKPhpNameAffix($fk, $plural = true)."();
\$obj2->add".$joinedTableObjectBuilder->getRefFKPhpNameAffix($fk, $plural = false)."(\$obj1); //CHECKME
}
\$results[] = \$obj1;
}
return \$results;
}
";
} // if fk table name != this table name
} // if ! is reference only
} // foreach column
} // if count(fk) > 1
} // addDoSelectJoin()
/**
* Adds the doCountJoin*() methods.
* @param string &$script The script will be modified in this method.
*/
protected function addDoCountJoin(&$script)
{
$table = $this->getTable();
$className = $table->getPhpName();
$countFK = count($table->getForeignKeys());
if ($countFK >= 1) {
foreach ($table->getForeignKeys() as $fk) {
$joinTable = $table->getDatabase()->getTable($fk->getForeignTableName());
if (!$joinTable->isForReferenceOnly()) {
if ( $fk->getForeignTableName() != $table->getName() ) {
$joinClassName = $joinTable->getPhpName();
$thisTableObjectBuilder = OMBuilder::getNewObjectBuilder($table);
$joinedTableObjectBuilder = OMBuilder::getNewObjectBuilder($joinTable);
$joinedTablePeerBuilder = OMBuilder::getNewPeerBuilder($joinTable);
$script .= "
/**
* Returns the number of rows matching criteria, joining the related ".$thisTableObjectBuilder->getFKPhpNameAffix($fk, $plural = false)." table
*
* @param Criteria \$c
* @param boolean \$distinct Whether to select only distinct columns (You can also set DISTINCT modifier in Criteria).
* @param Connection \$con
* @return int Number of matching rows.
*/
public static function doCountJoin".$thisTableObjectBuilder->getFKPhpNameAffix($fk, $plural = false)."(Criteria \$criteria, \$distinct = false, \$con = null)
{
// we're going to modify criteria, so copy it first
\$criteria = clone \$criteria;
// clear out anything that might confuse the ORDER BY clause
\$criteria->clearSelectColumns()->clearOrderByColumns();
if (\$distinct || in_array(Criteria::DISTINCT, \$criteria->getSelectModifiers())) {
\$criteria->addSelectColumn(".$this->getPeerClassname()."::COUNT_DISTINCT);
} else {
\$criteria->addSelectColumn(".$this->getPeerClassname()."::COUNT);
}
// just in case we're grouping: add those columns to the select statement
foreach(\$criteria->getGroupByColumns() as \$column)
{
\$criteria->addSelectColumn(\$column);
}
";
$lfMap = $fk->getLocalForeignMapping();
foreach ($fk->getLocalColumns() as $columnName ) {
$column = $table->getColumn($columnName);
$columnFk = $joinTable->getColumn( $lfMap[$columnName] );
$script .= "
\$criteria->addJoin(".$this->getColumnConstant($column).", ".$joinedTablePeerBuilder->getColumnConstant($columnFk).");
";
}
$script .= "
\$rs = ".$this->getPeerClassname()."::doSelectRS(\$criteria, \$con);
if (\$rs->next()) {
return \$rs->getInt(1);
} else {
// no rows returned; we infer that means 0 matches.
return 0;
}
}
";
} // if fk table name != this table name
} // if ! is reference only
} // foreach column
} // if count(fk) > 1
} // addDoCountJoin()
/**
* Adds the doSelectJoinAll() method.
* @param string &$script The script will be modified in this method.
*/
protected function addDoSelectJoinAll(&$script)
{
$table = $this->getTable();
$className = $table->getPhpName();
$script .= "
/**
* Selects a collection of $className objects pre-filled with all related objects.
*
* @return array Array of $className objects.
* @throws PropelException Any exceptions caught during processing will be
* rethrown wrapped into a PropelException.
*/
public static function doSelectJoinAll(Criteria \$c, \$con = null)
{
\$c = clone \$c;
// Set the correct dbName if it has not been overridden
if (\$c->getDbName() == Propel::getDefaultDB()) {
\$c->setDbName(self::DATABASE_NAME);
}
".$this->getPeerClassname()."::addSelectColumns(\$c);
\$startcol2 = (".$this->getPeerClassname()."::NUM_COLUMNS - ".$this->getPeerClassname()."::NUM_LAZY_LOAD_COLUMNS) + 1;
";
$index = 2;
foreach ($table->getForeignKeys() as $fk) {
// want to cover this case, but the code is not there yet.
// FIXME: why "is the code not there yet" ?
if ( $fk->getForeignTableName() != $table->getName() ) {
$joinTable = $table->getDatabase()->getTable($fk->getForeignTableName());
$joinClassName = $joinTable->getPhpName();
$new_index = $index + 1;
$joinedTablePeerBuilder = OMBuilder::getNewPeerBuilder($joinTable);
$script .= "
".$joinedTablePeerBuilder->getPeerClassname()."::addSelectColumns(\$c);
\$startcol$new_index = \$startcol$index + ".$joinedTablePeerBuilder->getPeerClassname()."::NUM_COLUMNS;
";
$index = $new_index;
} // if fk->getForeignTableName != table->getName
} // foreach [sub] foreign keys
foreach ($table->getForeignKeys() as $fk) {
// want to cover this case, but the code is not there yet.
if ( $fk->getForeignTableName() != $table->getName() ) {
$joinTable = $table->getDatabase()->getTable($fk->getForeignTableName());
$joinedTablePeerBuilder = OMBuilder::getNewPeerBuilder($joinTable);
$joinClassName = $joinTable->getPhpName();
$lfMap = $fk->getLocalForeignMapping();
foreach ($fk->getLocalColumns() as $columnName ) {
$column = $table->getColumn($columnName);
$columnFk = $joinTable->getColumn( $lfMap[$columnName]);
$script .= "
\$c->addJoin(".$this->getColumnConstant($column).", ".$joinedTablePeerBuilder->getColumnConstant($columnFk).");
";
}
}
}
$script .= "
\$rs = ".$this->basePeerClassname."::doSelect(\$c, \$con);
\$results = array();
while(\$rs->next()) {
";
if ($table->getChildrenColumn()) {
$script .= "
\$omClass = ".$this->getPeerClassname()."::getOMClass(\$rs, 1);
";
} else {
$script .= "
\$omClass = ".$this->getPeerClassname()."::getOMClass();
";
}
$script .= "
\$cls = Propel::import(\$omClass);
\$obj1 = new \$cls();
\$obj1->hydrate(\$rs);
";
$index = 1;
foreach ($table->getForeignKeys() as $fk ) {
// want to cover this case, but the code is not there yet.
// FIXME -- why not? -because we'd have to alias the tables in the JOIN
if ( $fk->getForeignTableName() != $table->getName() ) {
$joinTable = $table->getDatabase()->getTable($fk->getForeignTableName());
$joinClassName = $joinTable->getPhpName();
$interfaceName = $joinTable->getPhpName();
if($joinTable->getInterface()) {
$interfaceName = $joinTable->getInterface();
}
/*
$partJoinName = "";
foreach ($fk->getLocalColumns() as $columnName ) {
$column = $table->getColumn($columnName);
if ($column->isMultipleFK()) {
$partJoinName .= $column->getPhpName();
}
}
if ($partJoinName == "") {
$joinString = $interfaceName;
$collThisTable = "${className}s";
$collThisTableMs = $className;
} else {
$joinString= $interfaceName."RelatedBy" . $partJoinName;
$collThisTable= $className . "sRelatedBy" . $partJoinName;
$collThisTableMs= $className . "RelatedBy" . $partJoinName;
}
*/
$thisTableObjectBuilder = OMBuilder::getNewObjectBuilder($table);
$joinedTableObjectBuilder = OMBuilder::getNewObjectBuilder($joinTable);
$joinedTablePeerBuilder = OMBuilder::getNewPeerBuilder($joinTable);
$index++;
$script .= "
// Add objects for joined $joinClassName rows
";
if ($joinTable->getChildrenColumn()) {
$script .= "
\$omClass = ".$joinedTablePeerBuilder->getPeerClassname()."::getOMClass(\$rs, \$startcol$index);
";
} else {
$script .= "
\$omClass = ".$joinedTablePeerBuilder->getPeerClassname()."::getOMClass();
";
} /* $joinTable->getChildrenColumn() */
$script .= "
\$cls = Propel::import(\$omClass);
\$obj".$index." = new \$cls();
\$obj".$index."->hydrate(\$rs, \$startcol$index);
\$newObject = true;
for (\$j=0, \$resCount=count(\$results); \$j < \$resCount; \$j++) {
\$temp_obj1 = \$results[\$j];
\$temp_obj$index = \$temp_obj1->get".$thisTableObjectBuilder->getFKPhpNameAffix($fk, $plural = false)."(); // CHECKME
if (\$temp_obj".$index."->getPrimaryKey() === \$obj".$index."->getPrimaryKey()) {
\$newObject = false;
\$temp_obj".$index."->add".$joinedTableObjectBuilder->getRefFKPhpNameAffix($fk, $plural = false)."(\$obj1); // CHECKME
break;
}
}
if (\$newObject) {
\$obj".$index."->init".$joinedTableObjectBuilder->getRefFKPhpNameAffix($fk, $plural = true)."();
\$obj".$index."->add".$joinedTableObjectBuilder->getRefFKPhpNameAffix($fk, $plural = false)."(\$obj1);
}
";
} // $fk->getForeignTableName() != $table->getName()
} //foreach foreign key
$script .= "
\$results[] = \$obj1;
}
return \$results;
}
";
} // end addDoSelectJoinAll()
/**
* Adds the doCountJoinAll() method.
* @param string &$script The script will be modified in this method.
*/
protected function addDoCountJoinAll(&$script)
{
$table = $this->getTable();
$className = $table->getPhpName();
$script .= "
/**
* Returns the number of rows matching criteria, joining all related tables
*
* @param Criteria \$c
* @param boolean \$distinct Whether to select only distinct columns (You can also set DISTINCT modifier in Criteria).
* @param Connection \$con
* @return int Number of matching rows.
*/
public static function doCountJoinAll(Criteria \$criteria, \$distinct = false, \$con = null)
{
\$criteria = clone \$criteria;
// clear out anything that might confuse the ORDER BY clause
\$criteria->clearSelectColumns()->clearOrderByColumns();
if (\$distinct || in_array(Criteria::DISTINCT, \$criteria->getSelectModifiers())) {
\$criteria->addSelectColumn(".$this->getPeerClassname()."::COUNT_DISTINCT);
} else {
\$criteria->addSelectColumn(".$this->getPeerClassname()."::COUNT);
}
// just in case we're grouping: add those columns to the select statement
foreach(\$criteria->getGroupByColumns() as \$column)
{
\$criteria->addSelectColumn(\$column);
}
";
foreach ($table->getForeignKeys() as $fk) {
// want to cover this case, but the code is not there yet.
if ( $fk->getForeignTableName() != $table->getName() ) {
$joinTable = $table->getDatabase()->getTable($fk->getForeignTableName());
$joinedTablePeerBuilder = OMBuilder::getNewPeerBuilder($joinTable);
$joinClassName = $joinTable->getPhpName();
$lfMap = $fk->getLocalForeignMapping();
foreach ($fk->getLocalColumns() as $columnName ) {
$column = $table->getColumn($columnName);
$columnFk = $joinTable->getColumn( $lfMap[$columnName]);
$script .= "
\$criteria->addJoin(".$this->getColumnConstant($column).", ".$joinedTablePeerBuilder->getColumnConstant($columnFk).");
";
}
} // if fk->getForeignTableName != table->getName
} // foreach [sub] foreign keys
$script .= "
\$rs = ".$this->getPeerClassname()."::doSelectRS(\$criteria, \$con);
if (\$rs->next()) {
return \$rs->getInt(1);
} else {
// no rows returned; we infer that means 0 matches.
return 0;
}
}
";
} // end addDoCountJoinAll()
/**
* Adds the doSelectJoinAllExcept*() methods.
* @param string &$script The script will be modified in this method.
*/
protected function addDoSelectJoinAllExcept(&$script)
{
$table = $this->getTable();
// ------------------------------------------------------------------------
// doSelectJoinAllExcept*()
// ------------------------------------------------------------------------
// 2) create a bunch of doSelectJoinAllExcept*() methods
// -- these were existing in original Torque, so we should keep them for compatibility
$fkeys = $table->getForeignKeys(); // this sep assignment is necessary otherwise sub-loops over
// getForeignKeys() will cause this to only execute one time.
foreach ($fkeys as $fk ) {
$tblFK = $table->getDatabase()->getTable($fk->getForeignTableName());
$excludedTable = $table->getDatabase()->getTable($fk->getForeignTableName());
$excludedClassName = $excludedTable->getPhpName();
/*
$relatedByCol = "";
foreach ($fk->getLocalColumns() as $columnName) {
$column = $table->getColumn($columnName);
if ($column->isMultipleFK()) {
$relatedByCol .= $column->getPhpName();
}
}
if ($relatedByCol == "") {
$excludeString = $excludedClassName;
$collThisTable = "${className}s";
$collThisTableMs = $className;
} else {
$excludeString = $excludedClassName . "RelatedBy" . $relatedByCol;
$collThisTable = $className . "sRelatedBy" . $relatedByCol;
$collThisTableMs = $className . "RelatedBy" . $relatedByCol;
}
*/
$thisTableObjectBuilder = OMBuilder::getNewObjectBuilder($table);
$excludedTableObjectBuilder = OMBuilder::getNewObjectBuilder($excludedTable);
$excludedTablePeerBuilder = OMBuilder::getNewPeerBuilder($excludedTable);
$script .= "
/**
* Selects a collection of ".$table->getPhpName()." objects pre-filled with all related objects except ".$thisTableObjectBuilder->getFKPhpNameAffix($fk).".
*
* @return array Array of ".$table->getPhpName()." objects.
* @throws PropelException Any exceptions caught during processing will be
* rethrown wrapped into a PropelException.
*/
public static function doSelectJoinAllExcept".$thisTableObjectBuilder->getFKPhpNameAffix($fk, $plural = false)."(Criteria \$c, \$con = null)
{
\$c = clone \$c;
// Set the correct dbName if it has not been overridden
// \$c->getDbName() will return the same object if not set to another value
// so == check is okay and faster
if (\$c->getDbName() == Propel::getDefaultDB()) {
\$c->setDbName(self::DATABASE_NAME);
}
".$this->getPeerClassname()."::addSelectColumns(\$c);
\$startcol2 = (".$this->getPeerClassname()."::NUM_COLUMNS - ".$this->getPeerClassname()."::NUM_LAZY_LOAD_COLUMNS) + 1;
";
$index = 2;
foreach ($table->getForeignKeys() as $subfk) {
// want to cover this case, but the code is not there yet.
// FIXME - why not?
if ( !($subfk->getForeignTableName() == $table->getName())) {
$joinTable = $table->getDatabase()->getTable($subfk->getForeignTableName());
$joinClassName = $joinTable->getPhpName();
$joinTablePeerBuilder = OMBuilder::getNewPeerBuilder($joinTable);
if ($joinClassName != $excludedClassName) {
$new_index = $index + 1;
$script .= "
".$joinTablePeerBuilder->getPeerClassname()."::addSelectColumns(\$c);
\$startcol$new_index = \$startcol$index + ".$joinTablePeerBuilder->getPeerClassname()."::NUM_COLUMNS;
";
$index = $new_index;
} // if joinClassName not excludeClassName
} // if subfk is not curr table
} // foreach [sub] foreign keys
foreach ($table->getForeignKeys() as $subfk) {
// want to cover this case, but the code is not there yet.
if ( $subfk->getForeignTableName() != $table->getName() ) {
$joinTable = $table->getDatabase()->getTable($subfk->getForeignTableName());
$joinClassName = $joinTable->getPhpName();
$joinTablePeerBuilder = OMBuilder::getNewPeerBuilder($joinTable);
if($joinClassName != $excludedClassName)
{
$lfMap = $subfk->getLocalForeignMapping();
foreach ($subfk->getLocalColumns() as $columnName ) {
$column = $table->getColumn($columnName);
$columnFk = $joinTable->getColumn( $lfMap[$columnName]);
$script .= "
\$c->addJoin(".$this->getColumnConstant($column).", ".$joinTablePeerBuilder->getColumnConstant($columnFk).");
";
}
}
}
} // foreach fkeys
$script .= "
\$rs = ".$this->basePeerClassname ."::doSelect(\$c, \$con);
\$results = array();
while(\$rs->next()) {
";
if ($table->getChildrenColumn()) {
$script .= "
\$omClass = ".$this->getPeerClassname()."::getOMClass(\$rs, 1);
";
} else {
$script .= "
\$omClass = ".$this->getPeerClassname()."::getOMClass();
";
}
$script .= "
\$cls = Propel::import(\$omClass);
\$obj1 = new \$cls();
\$obj1->hydrate(\$rs);
";
$index = 1;
foreach ($table->getForeignKeys() as $subfk ) {
// want to cover this case, but the code is not there yet.
if ( $subfk->getForeignTableName() != $table->getName() ) {
$joinTable = $table->getDatabase()->getTable($subfk->getForeignTableName());
$joinClassName = $joinTable->getPhpName();
$interfaceName = $joinTable->getPhpName();
if($joinTable->getInterface()) {
$interfaceName = $joinTable->getInterface();
}
if ($joinClassName != $excludedClassName) {
/*
$partJoinName = "";
foreach ($subfk->getLocalColumns() as $columnName ) {
$column = $table->getColumn($columnName);
if ($column->isMultipleFK()) {
$partJoinName .= $column->getPhpName();
}
}
if ($partJoinName == "") {
$joinString = $interfaceName;
$collThisTable = "${className}s";
$collThisTableMs = $className;
} else {
$joinString= $interfaceName."RelatedBy" . $partJoinName;
$collThisTable= $className . "sRelatedBy" . $partJoinName;
$collThisTableMs= $className . "RelatedBy" . $partJoinName;
}
*/
$joinedTableObjectBuilder = OMBuilder::getNewObjectBuilder($joinTable);
$joinedTablePeerBuilder = OMBuilder::getNewPeerBuilder($joinTable);
$index++;
if ($joinTable->getChildrenColumn()) {
$script .= "
\$omClass = ".$joinedTablePeerBuilder->getPeerClassname()."::getOMClass(\$rs, \$startcol$index);
";
} else {
$script .= "
\$omClass = ".$joinedTablePeerBuilder->getPeerClassname()."::getOMClass();
";
} /* $joinTable->getChildrenColumn() */
$script .= "
\$cls = Propel::import(\$omClass);
\$obj$index = new \$cls();
\$obj".$index."->hydrate(\$rs, \$startcol$index);
\$newObject = true;
for (\$j=0, \$resCount=count(\$results); \$j < \$resCount; \$j++) {
\$temp_obj1 = \$results[\$j];
\$temp_obj$index = \$temp_obj1->get".$thisTableObjectBuilder->getFKPhpNameAffix($subfk, $plural=false)."(); //CHECKME
if (\$temp_obj".$index."->getPrimaryKey() === \$obj".$index."->getPrimaryKey()) {
\$newObject = false;
\$temp_obj".$index."->add".$joinedTableObjectBuilder->getRefFKPhpNameAffix($subfk, $plural=false)."(\$obj1);
break;
}
}
if (\$newObject) {
\$obj".$index."->init".$joinedTableObjectBuilder->getRefFKPhpNameAffix($subfk, $plural=true)."();
\$obj".$index."->add".$joinedTableObjectBuilder->getRefFKPhpNameAffix($subfk, $plural=false)."(\$obj1);
}
";
} // if ($joinClassName != $excludedClassName) {
} // $subfk->getForeignTableName() != $table->getName()
} // foreach
$script .= "
\$results[] = \$obj1;
}
return \$results;
}
";
} // foreach fk
} // addDoSelectJoinAllExcept
/**
* Adds the doCountJoinAllExcept*() methods.
* @param string &$script The script will be modified in this method.
*/
protected function addDoCountJoinAllExcept(&$script)
{
$table = $this->getTable();
$fkeys = $table->getForeignKeys(); // this sep assignment is necessary otherwise sub-loops over
// getForeignKeys() will cause this to only execute one time.
foreach ($fkeys as $fk ) {
$tblFK = $table->getDatabase()->getTable($fk->getForeignTableName());
$excludedTable = $table->getDatabase()->getTable($fk->getForeignTableName());
$excludedClassName = $excludedTable->getPhpName();
$thisTableObjectBuilder = OMBuilder::getNewObjectBuilder($table);
$excludedTableObjectBuilder = OMBuilder::getNewObjectBuilder($excludedTable);
$excludedTablePeerBuilder = OMBuilder::getNewPeerBuilder($excludedTable);
$script .= "
/**
* Returns the number of rows matching criteria, joining the related ".$thisTableObjectBuilder->getFKPhpNameAffix($fk, $plural = false)." table
*
* @param Criteria \$c
* @param boolean \$distinct Whether to select only distinct columns (You can also set DISTINCT modifier in Criteria).
* @param Connection \$con
* @return int Number of matching rows.
*/
public static function doCountJoinAllExcept".$thisTableObjectBuilder->getFKPhpNameAffix($fk, $plural = false)."(Criteria \$criteria, \$distinct = false, \$con = null)
{
// we're going to modify criteria, so copy it first
\$criteria = clone \$criteria;
// clear out anything that might confuse the ORDER BY clause
\$criteria->clearSelectColumns()->clearOrderByColumns();
if (\$distinct || in_array(Criteria::DISTINCT, \$criteria->getSelectModifiers())) {
\$criteria->addSelectColumn(".$this->getPeerClassname()."::COUNT_DISTINCT);
} else {
\$criteria->addSelectColumn(".$this->getPeerClassname()."::COUNT);
}
// just in case we're grouping: add those columns to the select statement
foreach(\$criteria->getGroupByColumns() as \$column)
{
\$criteria->addSelectColumn(\$column);
}
";
foreach ($table->getForeignKeys() as $subfk) {
// want to cover this case, but the code is not there yet.
if ( $subfk->getForeignTableName() != $table->getName() ) {
$joinTable = $table->getDatabase()->getTable($subfk->getForeignTableName());
$joinClassName = $joinTable->getPhpName();
$joinTablePeerBuilder = OMBuilder::getNewPeerBuilder($joinTable);
if($joinClassName != $excludedClassName)
{
$lfMap = $subfk->getLocalForeignMapping();
foreach ($subfk->getLocalColumns() as $columnName ) {
$column = $table->getColumn($columnName);
$columnFk = $joinTable->getColumn( $lfMap[$columnName]);
$script .= "
\$criteria->addJoin(".$this->getColumnConstant($column).", ".$joinTablePeerBuilder->getColumnConstant($columnFk).");
";
}
}
}
} // foreach fkeys
$script .= "
\$rs = ".$this->getPeerClassname()."::doSelectRS(\$criteria, \$con);
if (\$rs->next()) {
return \$rs->getInt(1);
} else {
// no rows returned; we infer that means 0 matches.
return 0;
}
}
";
} // foreach fk
} // addDoCountJoinAllExcept
} // PHP5ComplexPeerBuilder

View File

@ -0,0 +1,124 @@
<?php
/*
* $Id: PHP5ExtensionNodeBuilder.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/om/ObjectBuilder.php';
/**
* Generates the empty PHP5 stub node object class for user object model (OM).
*
* This class produces the empty stub class that can be customized with application
* business logic, custom behavior, etc.
*
* This class replaces the ExtensionNode.tpl, with the intent of being easier for users
* to customize (through extending & overriding).
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.om.php5
*/
class PHP5ExtensionNodeBuilder extends ObjectBuilder {
/**
* Returns the name of the current class being built.
* @return string
*/
public function getClassname()
{
return $this->getTable()->getPhpName() . 'Node';
}
/**
* Adds the include() statements for files that this class depends on or utilizes.
* @param string &$script The script will be modified in this method.
*/
protected function addIncludes(&$script)
{
$script .= "
require_once '".$this->getNodeBuilder()->getClassFilePath()."';
";
} // addIncludes()
/**
* Adds class phpdoc comment and openning of class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassOpen(&$script)
{
$table = $this->getTable();
$tableName = $table->getName();
$tableDesc = $table->getDescription();
$baseClassname = $this->getNodeBuilder()->getClassname();
$script .= "
/**
* Skeleton subclass for representing a node from the '$tableName' table.
*
* $tableDesc
*";
if ($this->getBuildProperty('addTimeStamp')) {
$now = strftime('%c');
$script .= "
* This class was autogenerated by Propel on:
*
* $now
*";
}
$script .= "
* You should add additional methods to this class to meet the
* application requirements. This class will only be generated as
* long as it does not already exist in the output directory.
*
* @package ".$this->getPackage()."
*/
class ".$this->getClassname()." extends $baseClassname {
";
}
/**
* Specifies the methods that are added as part of the stub object class.
*
* By default there are no methods for the empty stub classes; override this method
* if you want to change that behavior.
*
* @see ObjectBuilder::addClassBody()
*/
protected function addClassBody(&$script)
{
// there is no class body
}
/**
* Closes class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassClose(&$script)
{
$script .= "
} // " . $this->getClassname() . "
";
}
} // PHP5ExtensionObjectBuilder

View File

@ -0,0 +1,127 @@
<?php
/*
* $Id: PHP5ExtensionNodePeerBuilder.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/om/PeerBuilder.php';
/**
* Generates the empty PHP5 stub node peer class for user object model (OM).
*
* This class produces the empty stub class that can be customized with application
* business logic, custom behavior, etc.
*
* This class replaces the ExtensionNodePeer.tpl, with the intent of being easier for users
* to customize (through extending & overriding).
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.om.php5
*/
class PHP5ExtensionNodePeerBuilder extends PeerBuilder {
/**
* Returns the name of the current class being built.
* @return string
*/
public function getClassname()
{
return $this->getStubNodeBuilder()->getClassname() . 'Peer';
}
/**
* Adds the include() statements for files that this class depends on or utilizes.
* @param string &$script The script will be modified in this method.
*/
protected function addIncludes(&$script)
{
$script .= "
// include base nodepeer class
require_once '".$this->getNodePeerBuilder()->getClassFilePath()."';
// include node class
include_once '".$this->getStubNodeBuilder()->getClassFilePath()."';
";
} // addIncludes()
/**
* Adds class phpdoc comment and openning of class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassOpen(&$script)
{
$table = $this->getTable();
$tableName = $table->getName();
$tableDesc = $table->getDescription();
$baseClassname = $this->getNodePeerBuilder()->getClassname();
$script .= "
/**
* Skeleton subclass for performing query and update operations on nodes of the '$tableName' table.
*
* $tableDesc
*";
if ($this->getBuildProperty('addTimeStamp')) {
$now = strftime('%c');
$script .= "
* This class was autogenerated by Propel on:
*
* $now
*";
}
$script .= "
* You should add additional methods to this class to meet the
* application requirements. This class will only be generated as
* long as it does not already exist in the output directory.
*
* @package ".$this->getPackage()."
*/
class ".$this->getClassname()." extends $baseClassname {
";
}
/**
* Specifies the methods that are added as part of the stub peer class.
*
* By default there are no methods for the empty stub classes; override this method
* if you want to change that behavior.
*
* @see ObjectBuilder::addClassBody()
*/
protected function addClassBody(&$script)
{
// there is no class body
}
/**
* Closes class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassClose(&$script)
{
$script .= "
} // " . $this->getClassname() . "
";
}
} // PHP5ExtensionPeerBuilder

View File

@ -0,0 +1,123 @@
<?php
/*
* $Id: PHP5ExtensionObjectBuilder.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/om/ObjectBuilder.php';
/**
* Generates the empty PHP5 stub object class for user object model (OM).
*
* This class produces the empty stub class that can be customized with application
* business logic, custom behavior, etc.
*
* This class replaces the ExtensionObject.tpl, with the intent of being easier for users
* to customize (through extending & overriding).
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.om.php5
*/
class PHP5ExtensionObjectBuilder extends ObjectBuilder {
/**
* Returns the name of the current class being built.
* @return string
*/
public function getClassname()
{
return $this->getTable()->getPhpName();
}
/**
* Adds the include() statements for files that this class depends on or utilizes.
* @param string &$script The script will be modified in this method.
*/
protected function addIncludes(&$script)
{
$script .= "
require_once '".$this->getObjectBuilder()->getClassFilePath()."';
";
} // addIncludes()
/**
* Adds class phpdoc comment and openning of class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassOpen(&$script)
{
$table = $this->getTable();
$tableName = $table->getName();
$tableDesc = $table->getDescription();
$baseClassname = $this->getObjectBuilder()->getClassname();
$script .= "
/**
* Skeleton subclass for representing a row from the '$tableName' table.
*
* $tableDesc
*";
if ($this->getBuildProperty('addTimeStamp')) {
$now = strftime('%c');
$script .= "
* This class was autogenerated by Propel on:
*
* $now
*";
}
$script .= "
* You should add additional methods to this class to meet the
* application requirements. This class will only be generated as
* long as it does not already exist in the output directory.
*
* @package ".$this->getPackage()."
*/
class ".$this->getClassname()." extends $baseClassname {
";
}
/**
* Specifies the methods that are added as part of the stub object class.
*
* By default there are no methods for the empty stub classes; override this method
* if you want to change that behavior.
*
* @see ObjectBuilder::addClassBody()
*/
protected function addClassBody(&$script)
{
// there is no class body
}
/**
* Closes class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassClose(&$script)
{
$script .= "
} // " . $this->getClassname() . "
";
}
} // PHP5ExtensionObjectBuilder

View File

@ -0,0 +1,127 @@
<?php
/*
* $Id: PHP5ExtensionPeerBuilder.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/om/PeerBuilder.php';
/**
* Generates the empty PHP5 stub peer class for user object model (OM).
*
* This class produces the empty stub class that can be customized with application
* business logic, custom behavior, etc.
*
* This class replaces the ExtensionPeer.tpl, with the intent of being easier for users
* to customize (through extending & overriding).
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.om.php5
*/
class PHP5ExtensionPeerBuilder extends PeerBuilder {
/**
* Returns the name of the current class being built.
* @return string
*/
public function getClassname()
{
return $this->getStubObjectBuilder()->getClassname() . 'Peer';
}
/**
* Adds the include() statements for files that this class depends on or utilizes.
* @param string &$script The script will be modified in this method.
*/
protected function addIncludes(&$script)
{
$script .= "
// include base peer class
require_once '".$this->getPeerBuilder()->getClassFilePath()."';
// include object class
include_once '".$this->getStubObjectBuilder()->getClassFilePath()."';
";
} // addIncludes()
/**
* Adds class phpdoc comment and openning of class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassOpen(&$script)
{
$table = $this->getTable();
$tableName = $table->getName();
$tableDesc = $table->getDescription();
$baseClassname = $this->getPeerBuilder()->getClassname();
$script .= "
/**
* Skeleton subclass for performing query and update operations on the '$tableName' table.
*
* $tableDesc
*";
if ($this->getBuildProperty('addTimeStamp')) {
$now = strftime('%c');
$script .= "
* This class was autogenerated by Propel on:
*
* $now
*";
}
$script .= "
* You should add additional methods to this class to meet the
* application requirements. This class will only be generated as
* long as it does not already exist in the output directory.
*
* @package ".$this->getPackage()."
*/
class ".$this->getClassname()." extends $baseClassname {
";
}
/**
* Specifies the methods that are added as part of the stub peer class.
*
* By default there are no methods for the empty stub classes; override this method
* if you want to change that behavior.
*
* @see ObjectBuilder::addClassBody()
*/
protected function addClassBody(&$script)
{
// there is no class body
}
/**
* Closes class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassClose(&$script)
{
$script .= "
} // " . $this->getClassname() . "
";
}
} // PHP5ExtensionPeerBuilder

View File

@ -0,0 +1,119 @@
<?php
/*
* $Id: PHP5InterfaceBuilder.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/om/ObjectBuilder.php';
/**
* Generates the empty PHP5 stub interface for user object model (OM).
*
* This class produces the empty stub interface when the interface="" attribute is used
* in the the schema xml.
*
* This class replaces the Interface.tpl, with the intent of being easier for users
* to customize (through extending & overriding).
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.om.php5
*/
class PHP5InterfaceBuilder extends ObjectBuilder {
/**
* Returns the name of the current class being built.
* @return string
*/
public function getClassname()
{
return ClassTools::classname($this->getInterface());
}
/**
* Adds the include() statements for files that this class depends on or utilizes.
* @param string &$script The script will be modified in this method.
*/
protected function addIncludes(&$script)
{
} // addIncludes()
/**
* Adds class phpdoc comment and openning of class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassOpen(&$script)
{
$table = $this->getTable();
$tableName = $table->getName();
$tableDesc = $table->getDescription();
$baseClassname = $this->getObjectBuilder()->getClassname();
$script .= "
/**
* This is an interface that should be filled with the public api of the $tableName objects.
*
* $tableDesc
*";
if ($this->getBuildProperty('addTimeStamp')) {
$now = strftime('%c');
$script .= "
* This class was autogenerated by Propel on:
*
* $now
*";
}
$script .= "
* You should add additional method declarations to this interface to meet the
* application requirements. This interface will only be generated as
* long as it does not already exist in the output directory.
*
* @package ".$this->getPackage()."
*/
interface ".$this->getClassname()." {
";
}
/**
* Specifies the methods that are added as part of the stub object class.
*
* By default there are no methods for the empty stub classes; override this method
* if you want to change that behavior.
*
* @see ObjectBuilder::addClassBody()
*/
protected function addClassBody(&$script)
{
// there is no class body
}
/**
* Closes class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassClose(&$script)
{
$script .= "
} // " . $this->getClassname() . "
";
}
} // PHP5ExtensionObjectBuilder

View File

@ -0,0 +1,300 @@
<?php
/*
* $Id: PHP5MapBuilderBuilder.php 562 2007-02-01 02:17:24Z hans $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/om/OMBuilder.php';
/**
* Generates the PHP5 map builder class for user object model (OM).
*
* This class replaces the MapBuilder.tpl, with the intent of being easier for users
* to customize (through extending & overriding).
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.om.php5
*/
class PHP5MapBuilderBuilder extends OMBuilder {
/**
* Gets the package for the map builder classes.
* @return string
*/
public function getPackage()
{
return parent::getPackage() . '.map';
}
/**
* Returns the name of the current class being built.
* @return string
*/
public function getClassname()
{
return $this->getTable()->getPhpName() . 'MapBuilder';
}
/**
* Adds the include() statements for files that this class depends on or utilizes.
* @param string &$script The script will be modified in this method.
*/
protected function addIncludes(&$script)
{
$script .= "
require_once 'propel/map/MapBuilder.php';
include_once 'creole/CreoleTypes.php';
";
} // addIncludes()
/**
* Adds class phpdoc comment and openning of class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassOpen(&$script)
{
$table = $this->getTable();
$script .= "
/**
* This class adds structure of '".$table->getName()."' table to '".$table->getDatabase()->getName()."' DatabaseMap object.
*
*";
if ($this->getBuildProperty('addTimeStamp')) {
$now = strftime('%c');
$script .= "
* This class was autogenerated by Propel on:
*
* $now
*";
}
$script .= "
*
* These statically-built map classes are used by Propel to do runtime db structure discovery.
* For example, the createSelectSql() method checks the type of a given column used in an
* ORDER BY clause to know whether it needs to apply SQL to make the ORDER BY case-insensitive
* (i.e. if it's a text column type).
*
* @package ".$this->getPackage()."
*/
class ".$this->getClassname()." {
";
}
/**
* Specifies the methods that are added as part of the map builder class.
* This can be overridden by subclasses that wish to add more methods.
* @see ObjectBuilder::addClassBody()
*/
protected function addClassBody(&$script)
{
$this->addConstants($script);
$this->addAttributes($script);
$this->addIsBuilt($script);
$this->addGetDatabaseMap($script);
$this->addDoBuild($script);
}
/**
* Adds any constants needed for this MapBuilder class.
* @param string &$script The script will be modified in this method.
*/
protected function addConstants(&$script)
{
$script .= "
/**
* The (dot-path) name of this class
*/
const CLASS_NAME = '".$this->getClasspath()."';
";
}
/**
* Adds any attributes needed for this MapBuilder class.
* @param string &$script The script will be modified in this method.
*/
protected function addAttributes(&$script)
{
$script .= "
/**
* The database map.
*/
private \$dbMap;
";
}
/**
* Closes class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassClose(&$script)
{
$script .= "
} // " . $this->getClassname() . "
";
}
/**
* Adds the method that indicates whether this map has already been built.
* @param string &$script The script will be modified in this method.
*/
protected function addIsBuilt(&$script)
{
$script .= "
/**
* Tells us if this DatabaseMapBuilder is built so that we
* don't have to re-build it every time.
*
* @return boolean true if this DatabaseMapBuilder is built, false otherwise.
*/
public function isBuilt()
{
return (\$this->dbMap !== null);
}
";
}
/**
* Adds the DatabaseMap accessor method.
* @param string &$script The script will be modified in this method.
*/
protected function addGetDatabaseMap(&$script)
{
$script .= "
/**
* Gets the databasemap this map builder built.
*
* @return the databasemap
*/
public function getDatabaseMap()
{
return \$this->dbMap;
}
";
}
/**
* Adds the main doBuild() method to the map builder class.
* @param string &$script The script will be modified in this method.
*/
protected function addDoBuild(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
$script .= "
/**
* The doBuild() method builds the DatabaseMap
*
* @return void
* @throws PropelException
*/
public function doBuild()
{
\$this->dbMap = Propel::getDatabaseMap('".$table->getDatabase()->getName()."');
\$tMap = \$this->dbMap->addTable('".$table->getName()."');
\$tMap->setPhpName('".$table->getPhpName()."');
";
if ($table->getIdMethod() == "native") {
$script .= "
\$tMap->setUseIdGenerator(true);
";
} else {
$script .= "
\$tMap->setUseIdGenerator(false);
";
}
if ($table->getIdMethodParameters()) {
$params = $table->getIdMethodParameters();
$imp = $params[0];
$script .= "
\$tMap->setPrimaryKeyMethodInfo('".$imp->getValue()."');
";
} elseif ($table->getIdMethod() == "native" && ($platform->getNativeIdMethod() == Platform::SEQUENCE)) {
$script .= "
\$tMap->setPrimaryKeyMethodInfo('".$table->getSequenceName()."');
";
} elseif ($table->getIdMethod() == "native" && ($platform->getNativeIdMethod() == Platform::SEQUENCE)) {
$script .= "
\$tMap->setPrimaryKeyMethodInfo('".$table->getName()."');
";
}
// Add columns to map
foreach ($table->getColumns() as $col) {
$tfc=$table->getPhpName();
$cfc=$col->getPhpName();
$cup=strtoupper($col->getName());
if (!$col->getSize()) {
$size = "null";
} else {
$size = $col->getSize();
}
if($col->isPrimaryKey()) {
if($col->isForeignKey()) {
$script .= "
\$tMap->addForeignPrimaryKey('$cup', '$cfc', '".$col->getPhpType()."' , CreoleTypes::".$col->getType().", '".$col->getRelatedTableName()."', '".strtoupper($col->getRelatedColumnName())."', ".($col->isNotNull() ? 'true' : 'false').", ".$size.");
";
} else {
$script .= "
\$tMap->addPrimaryKey('$cup', '$cfc', '".$col->getPhpType()."', CreoleTypes::".$col->getType().", ".var_export($col->isNotNull(), true).", ".$size.");
";
}
} else {
if($col->isForeignKey()) {
$script .= "
\$tMap->addForeignKey('$cup', '$cfc', '".$col->getPhpType()."', CreoleTypes::".$col->getType().", '".$col->getRelatedTableName()."', '".strtoupper($col->getRelatedColumnName())."', ".($col->isNotNull() ? 'true' : 'false').", ".$size.");
";
} else {
$script .= "
\$tMap->addColumn('$cup', '$cfc', '".$col->getPhpType()."', CreoleTypes::".$col->getType().", ".var_export($col->isNotNull(), true).", ".$size.");
";
}
} // if col-is prim key
} // foreach
foreach($table->getValidators() as $val) {
$col = $val->getColumn();
$cup = strtoupper($col->getName());
foreach($val->getRules() as $rule) {
if ($val->getTranslate() !== Validator::TRANSLATE_NONE) {
$script .= "
\$tMap->addValidator('$cup', '".$rule->getName()."', '".$rule->getClass()."', '".$rule->getValue()."', ".$val->getTranslate()."('".str_replace("'", "\'", $rule->getMessage())."'));
";
} else {
$script .= "
\$tMap->addValidator('$cup', '".$rule->getName()."', '".$rule->getClass()."', '".$rule->getValue()."', '".str_replace("'", "\'", $rule->getMessage())."');
";
} // if ($rule->getTranslation() ...
} // foreach rule
} // foreach validator
$script .= "
} // doBuild()
";
}
} // PHP5ExtensionPeerBuilder

View File

@ -0,0 +1,209 @@
<?php
/*
* $Id: PHP5MultiExtendObjectBuilder.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/om/ObjectBuilder.php';
/**
* Generates the empty PHP5 stub object class for use with inheritance in the user object model (OM).
*
* This class produces the empty stub class that can be customized with application
* business logic, custom behavior, etc.
*
* This class replaces the MultiExtendObject.tpl, with the intent of being easier for users
* to customize (through extending & overriding).
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.om.php5
*/
class PHP5MultiExtendObjectBuilder extends ObjectBuilder {
/**
* The current child "object" we are operating on.
*/
private $child;
/**
* Returns the name of the current class being built.
* @return string
*/
public function getClassname()
{
return $this->getChild()->getClassName();
}
/**
* Override method to return child package, if specified.
* @return string
*/
public function getPackage()
{
return ($this->child->getPackage() ? $this->child->getPackage() : parent::getPackage());
}
/**
* Set the child object that we're operating on currrently.
* @param $child Inheritance
*/
public function setChild(Inheritance $child)
{
$this->child = $child;
}
/**
* Returns the child object we're operating on currently.
* @return Inheritance
* @throws BuildException - if child was not set.
*/
public function getChild()
{
if (!$this->child) {
throw new BuildException("The PHP5MultiExtendObjectBuilder needs to be told which child class to build (via setChild() method) before it can build the stub class.");
}
return $this->child;
}
/**
* Returns classpath to parent class.
* @return string
*/
protected function getParentClasspath()
{
if ($this->getChild()->getAncestor()) {
return $this->getChild()->getAncestor();
} else {
return $this->getObjectBuilder()->getClasspath();
}
}
/**
* Returns classname of parent class.
* @return string
*/
protected function getParentClassname()
{
return ClassTools::classname($this->getParentClasspath());
}
/**
* Gets the file path to the parent class.
* @return string
*/
protected function getParentClassFilePath()
{
return $this->getFilePath($this->getParentClasspath());
}
/**
* Adds the include() statements for files that this class depends on or utilizes.
* @param string &$script The script will be modified in this method.
*/
protected function addIncludes(&$script)
{
$script .= "
require_once '".$this->getParentClassFilePath()."';
";
$script .= "
require_once '".$this->getObjectBuilder()->getClassFilePath()."';
";
} // addIncludes()
/**
* Adds class phpdoc comment and openning of class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassOpen(&$script)
{
$table = $this->getTable();
$tableName = $table->getName();
$tableDesc = $table->getDescription();
$baseClassname = $this->getObjectBuilder()->getClassname();
$script .= "
/**
* Skeleton subclass for representing a row from one of the subclasses of the '$tableName' table.
*
* $tableDesc
*";
if ($this->getBuildProperty('addTimeStamp')) {
$now = strftime('%c');
$script .= "
* This class was autogenerated by Propel on:
*
* $now
*";
}
$script .= "
* You should add additional methods to this class to meet the
* application requirements. This class will only be generated as
* long as it does not already exist in the output directory.
*
* @package ".$this->getPackage()."
*/
class ".$this->getClassname()." extends ".$this->getParentClassname()." {
";
}
/**
* Specifies the methods that are added as part of the stub object class.
*
* By default there are no methods for the empty stub classes; override this method
* if you want to change that behavior.
*
* @see ObjectBuilder::addClassBody()
*/
protected function addClassBody(&$script)
{
$child = $this->getChild();
$col = $child->getColumn();
$cfc = $col->getPhpName();
$const = "CLASSKEY_".strtoupper($child->getKey());
$script .= "
/**
* Constructs a new ".$this->getChild()->getClassName()." class, setting the ".$col->getName()." column to ".$this->getPeerClassname()."::$const.
*/
public function __construct()
{
";
$script .= "
\$this->set$cfc(".$this->getPeerClassname()."::CLASSKEY_".strtoupper($child->getKey()).");
}
";
}
/**
* Closes class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassClose(&$script)
{
$script .= "
} // " . $this->getClassname() . "
";
}
} // PHP5ExtensionObjectBuilder

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,774 @@
<?php
/*
* $Id: PHP5NodePeerBuilder.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/om/PeerBuilder.php';
/**
* Generates a PHP5 tree node Peer class for user object model (OM).
*
* This class produces the base tree node object class (e.g. BaseMyTable) which contains all
* the custom-built accessor and setter methods.
*
* This class replaces the Node.tpl, with the intent of being easier for users
* to customize (through extending & overriding).
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.om.php5
*/
class PHP5NodePeerBuilder extends PeerBuilder {
/**
* Gets the package for the [base] object classes.
* @return string
*/
public function getPackage()
{
return parent::getPackage() . ".om";
}
/**
* Returns the name of the current class being built.
* @return string
*/
public function getClassname()
{
return $this->getBuildProperty('basePrefix') . $this->getStubNodePeerBuilder()->getClassname();
}
/**
* Adds the include() statements for files that this class depends on or utilizes.
* @param string &$script The script will be modified in this method.
*/
protected function addIncludes(&$script)
{
$script .= "
require_once '".$this->getStubObjectBuilder()->getClassFilePath()."';
require_once '".$this->getStubNodeBuilder()->getClassFilePath()."';
";
} // addIncludes()
/**
* Adds class phpdoc comment and openning of class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassOpen(&$script)
{
$table = $this->getTable();
$tableName = $table->getName();
$tableDesc = $table->getDescription();
$script .= "
/**
* Base static class for performing query operations on the tree contained by the '$tableName' table.
*
* $tableDesc
*";
if ($this->getBuildProperty('addTimeStamp')) {
$now = strftime('%c');
$script .= "
* This class was autogenerated by Propel on:
*
* $now
*";
}
$script .= "
* @package ".$this->getPackage()."
*/
abstract class ".$this->getClassname()." {
";
}
/**
* Specifies the methods that are added as part of the basic OM class.
* This can be overridden by subclasses that wish to add more methods.
* @see ObjectBuilder::addClassBody()
*/
protected function addClassBody(&$script)
{
$table = $this->getTable();
// FIXME
// - Probably the build needs to be customized for supporting
// tables that are "aliases". -- definitely a fringe usecase, though.
$this->addConstants($script);
$this->addIsCodeBase($script);
$this->addRetrieveMethods($script);
$this->addCreateNewRootNode($script);
$this->addInsertNewRootNode($script);
$this->addMoveNodeSubTree($script);
$this->addDeleteNodeSubTree($script);
$this->addBuildFamilyCriteria($script);
$this->addBuildTree($script);
$this->addPopulateNodes($script);
}
/**
* Closes class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassClose(&$script)
{
$script .= "
} // " . $this->getClassname() . "
";
}
protected function addConstants(&$script)
{
$table = $this->getTable();
$npath_colname = '';
$npath_phpname = '';
$npath_len = 0;
$npath_sep = '';
foreach ($table->getColumns() as $col) {
if ($col->isNodeKey()) {
$npath_colname = $table->getName() . '.' . strtoupper($col->getName());
$npath_phpname = $col->getPhpName();
$npath_len = $col->getSize();
$npath_sep = $col->getNodeKeySep();
break;
}
}
$script .= "
const NPATH_COLNAME = '$npath_colname';
const NPATH_PHPNAME = '$npath_phpname';
const NPATH_SEP = '$npath_sep';
const NPATH_LEN = $npath_len;
";
}
protected function addIsCodeBase(&$script)
{
$peerClassname = $this->getStubPeerBuilder()->getClassname();
$nodePeerClassname = $this->getStubNodePeerBuilder()->getClassname();
$script .= "
/**
* Temp function for CodeBase hacks that will go away.
*/
public static function isCodeBase(\$con = null)
{
if (\$con === null)
\$con = Propel::getConnection($peerClassname::DATABASE_NAME);
return (get_class(\$con) == 'ODBCConnection' &&
get_class(\$con->getAdapter()) == 'CodeBaseAdapter');
}
";
}
protected function addCreateNewRootNode(&$script)
{
$peerClassname = $this->getStubPeerBuilder()->getClassname();
$objectClassname = $this->getStubObjectBuilder()->getClassname();
$nodePeerClassname = $this->getStubNodePeerBuilder()->getClassname();
$nodeObjectClassname = $this->getStubNodeBuilder()->getClassname();
$script .= "
/**
* Create a new Node at the top of tree. This method will destroy any
* existing root node (along with its children).
*
* Use at your own risk!
*
* @param $objectClassname Object wrapped by new node.
* @param Connection Connection to use.
* @return $nodeObjectClassname
* @throws PropelException
*/
public static function createNewRootNode(\$obj, \$con = null)
{
if (\$con === null)
\$con = Propel::getConnection($peerClassname::DATABASE_NAME);
try {
\$con->begin();
self::deleteNodeSubTree('1', \$con);
\$setNodePath = 'set' . self::NPATH_PHPNAME;
\$obj->\$setNodePath('1');
\$obj->save(\$con);
\$con->commit();
} catch (PropelException \$e) {
\$con->rollback();
throw \$e;
}
return new $nodeObjectClassname(\$obj);
}
";
}
protected function addInsertNewRootNode(&$script)
{
$peerClassname = $this->getStubPeerBuilder()->getClassname();
$objectClassname = $this->getStubObjectBuilder()->getClassname();
$nodePeerClassname = $this->getStubNodePeerBuilder()->getClassname();
$nodeObjectClassname = $this->getStubNodeBuilder()->getClassname();
$script .= "
/**
* Inserts a new Node at the top of tree. Any existing root node (along with
* its children) will be made a child of the new root node. This is a
* safer alternative to createNewRootNode().
*
* @param $objectClassname Object wrapped by new node.
* @param Connection Connection to use.
* @return $nodeObjectClassname
* @throws PropelException
*/
public static function insertNewRootNode(\$obj, \$con = null)
{
if (\$con === null)
\$con = Propel::getConnection($peerClassname::DATABASE_NAME);
try {
\$con->begin();
// Move root tree to an invalid node path.
$nodePeerClassname::moveNodeSubTree('1', '0', \$con);
\$setNodePath = 'set' . self::NPATH_PHPNAME;
// Insert the new root node.
\$obj->\$setNodePath('1');
\$obj->save(\$con);
// Move the old root tree as a child of the new root.
$nodePeerClassname::moveNodeSubTree('0', '1' . self::NPATH_SEP . '1', \$con);
\$con->commit();
} catch (PropelException \$e) {
\$con->rollback();
throw \$e;
}
return new $nodeObjectClassname(\$obj);
}
";
}
/**
* Adds the methods for retrieving nodes.
*/
protected function addRetrieveMethods(&$script)
{
$this->addRetrieveNodes($script);
$this->addRetrieveNodeByPK($script);
$this->addRetrieveNodeByNP($script);
$this->addRetrieveRootNode($script);
}
protected function addRetrieveNodes(&$script)
{
$peerClassname = $this->getStubPeerBuilder()->getClassname();
$nodePeerClassname = $this->getStubNodePeerBuilder()->getClassname();
$script .= "
/**
* Retrieves an array of tree nodes based on specified criteria. Optionally
* includes all parent and/or child nodes of the matching nodes.
*
* @param Criteria Criteria to use.
* @param boolean True if ancestors should also be retrieved.
* @param boolean True if descendants should also be retrieved.
* @param Connection Connection to use.
* @return array Array of root nodes.
*/
public static function retrieveNodes(\$criteria, \$ancestors = false, \$descendants = false, \$con = null)
{
\$criteria = $nodePeerClassname::buildFamilyCriteria(\$criteria, \$ancestors, \$descendants);
\$rs = ".$this->getStubPeerBuilder()->getClassname()."::doSelectRS(\$criteria, \$con);
return self::populateNodes(\$rs, \$criteria);
}
";
}
protected function addRetrieveNodeByPK(&$script)
{
$peerClassname = $this->getStubPeerBuilder()->getClassname();
$objectClassname = $this->getStubObjectBuilder()->getClassname();
$nodePeerClassname = $this->getStubNodePeerBuilder()->getClassname();
$nodeObjectClassname = $this->getStubNodeBuilder()->getClassname();
$script .= "
/**
* Retrieves a tree node based on a primary key. Optionally includes all
* parent and/or child nodes of the matching node.
*
* @param mixed $objectClassname primary key (array for composite keys)
* @param boolean True if ancestors should also be retrieved.
* @param boolean True if descendants should also be retrieved.
* @param Connection Connection to use.
* @return $nodeObjectClassname
*/
public static function retrieveNodeByPK(\$pk, \$ancestors = false, \$descendants = false, \$con = null)
{
throw new PropelException('retrieveNodeByPK() not implemented yet.');
}
";
}
protected function addRetrieveNodeByNP(&$script)
{
$peerClassname = $this->getStubPeerBuilder()->getClassname();
$objectClassname = $this->getStubObjectBuilder()->getClassname();
$nodePeerClassname = $this->getStubNodePeerBuilder()->getClassname();
$nodeObjectClassname = $this->getStubNodeBuilder()->getClassname();
$script .= "
/**
* Retrieves a tree node based on a node path. Optionally includes all
* parent and/or child nodes of the matching node.
*
* @param string Node path to retrieve.
* @param boolean True if ancestors should also be retrieved.
* @param boolean True if descendants should also be retrieved.
* @param Connection Connection to use.
* @return $objectClassname
*/
public static function retrieveNodeByNP(\$np, \$ancestors = false, \$descendants = false, \$con = null)
{
\$criteria = new Criteria($peerClassname::DATABASE_NAME);
\$criteria->add(self::NPATH_COLNAME, \$np, Criteria::EQUAL);
\$criteria = self::buildFamilyCriteria(\$criteria, \$ancestors, \$descendants);
\$rs = $peerClassname::doSelectRS(\$criteria, \$con);
\$nodes = self::populateNodes(\$rs, \$criteria);
return (count(\$nodes) == 1 ? \$nodes[0] : null);
}
";
}
protected function addRetrieveRootNode(&$script)
{
$script .= "
/**
* Retrieves the root node.
*
* @param string Node path to retrieve.
* @param boolean True if descendants should also be retrieved.
* @param Connection Connection to use.
* @return ".$this->getStubNodeBuilder()->getClassname()."
*/
public static function retrieveRootNode(\$descendants = false, \$con = null)
{
return self::retrieveNodeByNP('1', false, \$descendants, \$con);
}
";
}
protected function addMoveNodeSubTree(&$script)
{
$peerClassname = $this->getStubPeerBuilder()->getClassname();
$objectClassname = $this->getStubObjectBuilder()->getClassname();
$nodePeerClassname = $this->getStubNodePeerBuilder()->getClassname();
$nodeObjectClassname = $this->getStubNodeBuilder()->getClassname();
$script .= "
/**
* Moves the node subtree at srcpath to the dstpath. This method is intended
* for internal use by the BaseNode object. Note that it does not check for
* preexisting nodes at the dstpath. It also does not update the node path
* of any Node objects that might currently be in memory.
*
* Use at your own risk!
*
* @param string Source node path to move (root of the src subtree).
* @param string Destination node path to move to (root of the dst subtree).
* @param Connection Connection to use.
* @return void
* @throws PropelException
* @todo This is currently broken for simulated 'onCascadeDelete's.
* @todo Need to abstract the SQL better. The CONCAT sql function doesn't
* seem to be standardized (i.e. mssql), so maybe it needs to be moved
* to DBAdapter.
*/
public static function moveNodeSubTree(\$srcPath, \$dstPath, \$con = null)
{
if (substr(\$dstPath, 0, strlen(\$srcPath)) == \$srcPath)
throw new PropelException('Cannot move a node subtree within itself.');
if (\$con === null)
\$con = Propel::getConnection($peerClassname::DATABASE_NAME);
/**
* Example:
* UPDATE table
* SET npath = CONCAT('1.3', SUBSTRING(npath, 6, 74))
* WHERE npath = '1.2.2' OR npath LIKE '1.2.2.%'
*/
\$npath = $nodePeerClassname::NPATH_COLNAME;
//the following dot isn`t mean`t a nodeKeySeperator
\$setcol = substr(\$npath, strpos(\$npath, '.')+1);
\$setcollen = $nodePeerClassname::NPATH_LEN;
\$db = Propel::getDb($peerClassname::DATABASE_NAME);
// <hack>
if ($nodePeerClassname::isCodeBase(\$con))
{
// This is a hack to get CodeBase working. It will eventually be removed.
// It is a workaround for the following CodeBase bug:
// -Prepared statement parameters cannot be embedded in SQL functions (i.e. CONCAT)
\$sql = \"UPDATE \" . $peerClassname::TABLE_NAME . \" \" .
\"SET \$setcol=\" . \$db->concatString(\"'\$dstPath'\", \$db->subString(\$npath, strlen(\$srcPath)+1, \$setcollen)) . \" \" .
\"WHERE \$npath = '\$srcPath' OR \$npath LIKE '\" . \$srcPath . $nodePeerClassname::NPATH_SEP . \"%'\";
\$con->executeUpdate(\$sql);
}
else
{
// </hack>
\$sql = \"UPDATE \" . $peerClassname::TABLE_NAME . \" \" .
\"SET \$setcol=\" . \$db->concatString('?', \$db->subString(\$npath, '?', '?')) . \" \" .
\"WHERE \$npath = ? OR \$npath LIKE ?\";
\$stmt = \$con->prepareStatement(\$sql);
\$stmt->setString(1, \$dstPath);
\$stmt->setInt(2, strlen(\$srcPath)+1);
\$stmt->setInt(3, \$setcollen);
\$stmt->setString(4, \$srcPath);
\$stmt->setString(5, \$srcPath . $nodePeerClassname::NPATH_SEP . '%');
\$stmt->executeUpdate();
// <hack>
}
// </hack>
}
";
}
protected function addDeleteNodeSubTree(&$script)
{
$peerClassname = $this->getStubPeerBuilder()->getClassname();
$objectClassname = $this->getStubObjectBuilder()->getClassname();
$nodePeerClassname = $this->getStubNodePeerBuilder()->getClassname();
$nodeObjectClassname = $this->getStubNodeBuilder()->getClassname();
$script .= "
/**
* Deletes the node subtree at the specified node path from the database.
*
* @param string Node path to delete
* @param Connection Connection to use.
* @return void
* @throws PropelException
* @todo This is currently broken for simulated 'onCascadeDelete's.
*/
public static function deleteNodeSubTree(\$nodePath, \$con = null)
{
if (\$con === null)
\$con = Propel::getConnection($peerClassname::DATABASE_NAME);
/**
* DELETE FROM table
* WHERE npath = '1.2.2' OR npath LIKE '1.2.2.%'
*/
\$criteria = new Criteria($peerClassname::DATABASE_NAME);
\$criteria->add($nodePeerClassname::NPATH_COLNAME, \$nodePath, Criteria::EQUAL);
\$criteria->addOr($nodePeerClassname::NPATH_COLNAME, \$nodePath . self::NPATH_SEP . '%', Criteria::LIKE);
// For now, we call BasePeer directly since $peerClassname tries to
// do a cascade delete.
// $peerClassname::doDelete(\$criteria, \$con);
BasePeer::doDelete(\$criteria, \$con);
}
";
}
protected function addBuildFamilyCriteria(&$script)
{
$peerClassname = $this->getStubPeerBuilder()->getClassname();
$objectClassname = $this->getStubObjectBuilder()->getClassname();
$nodePeerClassname = $this->getStubNodePeerBuilder()->getClassname();
$nodeObjectClassname = $this->getStubNodeBuilder()->getClassname();
$script .= "
/**
* Builds the criteria needed to retrieve node ancestors and/or descendants.
*
* @param Criteria Criteria to start with
* @param boolean True if ancestors should be retrieved.
* @param boolean True if descendants should be retrieved.
* @return Criteria
*/
public static function buildFamilyCriteria(\$criteria, \$ancestors = false, \$descendants = false)
{
/*
Example SQL to retrieve nodepath '1.2.3' with both ancestors and descendants:
SELECT L.NPATH, L.LABEL, test.NPATH, UCASE(L.NPATH)
FROM test L, test
WHERE test.NPATH='1.2.3' AND
(L.NPATH=SUBSTRING(test.NPATH, 1, LENGTH(L.NPATH)) OR
test.NPATH=SUBSTRING(L.NPATH, 1, LENGTH(test.NPATH)))
ORDER BY UCASE(L.NPATH) ASC
*/
if (\$criteria === null)
\$criteria = new Criteria($peerClassname::DATABASE_NAME);
if (!\$criteria->getSelectColumns())
$peerClassname::addSelectColumns(\$criteria);
\$db = Propel::getDb(\$criteria->getDbName());
if ((\$ancestors || \$descendants) && \$criteria->size())
{
// If we are retrieving ancestors/descendants, we need to do a
// self-join to locate them. The exception to this is if no search
// criteria is specified. In this case we're retrieving all nodes
// anyway, so there is no need to do a self-join.
// The left-side of the self-join will contain the columns we'll
// use to build node objects (target node records along with their
// ancestors and/or descendants). The right-side of the join will
// contain the target node records specified by the initial criteria.
// These are used to match the appropriate ancestor/descendant on
// the left.
// Specify an alias for the left-side table to use.
\$criteria->addAlias('L', $peerClassname::TABLE_NAME);
// Make sure we have select columns to begin with.
if (!\$criteria->getSelectColumns())
$peerClassname::addSelectColumns(\$criteria);
// Replace any existing columns for the right-side table with the
// left-side alias.
\$selectColumns = \$criteria->getSelectColumns();
\$criteria->clearSelectColumns();
foreach (\$selectColumns as \$colName)
\$criteria->addSelectColumn(str_replace($peerClassname::TABLE_NAME, 'L', \$colName));
\$a = null;
\$d = null;
\$npathL = $peerClassname::alias('L', $nodePeerClassname::NPATH_COLNAME);
\$npathR = $nodePeerClassname::NPATH_COLNAME;
\$npath_len = $nodePeerClassname::NPATH_LEN;
if (\$ancestors)
{
// For ancestors, match left-side node paths which are contained
// by right-side node paths.
\$a = \$criteria->getNewCriterion(\$npathL,
\"\$npathL=\" . \$db->subString(\$npathR, 1, \$db->strLength(\$npathL), \$npath_len),
Criteria::CUSTOM);
}
if (\$descendants)
{
// For descendants, match left-side node paths which contain
// right-side node paths.
\$d = \$criteria->getNewCriterion(\$npathR,
\"\$npathR=\" . \$db->subString(\$npathL, 1, \$db->strLength(\$npathR), \$npath_len),
Criteria::CUSTOM);
}
if (\$a)
{
if (\$d) \$a->addOr(\$d);
\$criteria->addAnd(\$a);
}
else if (\$d)
{
\$criteria->addAnd(\$d);
}
// Add the target node path column. This is used by populateNodes().
\$criteria->addSelectColumn(\$npathR);
// Sort by node path to speed up tree construction in populateNodes()
\$criteria->addAsColumn('npathlen', \$db->strLength(\$npathL));
\$criteria->addAscendingOrderByColumn('npathlen');
\$criteria->addAscendingOrderByColumn(\$npathL);
}
else
{
// Add the target node path column. This is used by populateNodes().
\$criteria->addSelectColumn($nodePeerClassname::NPATH_COLNAME);
// Sort by node path to speed up tree construction in populateNodes()
\$criteria->addAsColumn('npathlen', \$db->strLength($nodePeerClassname::NPATH_COLNAME));
\$criteria->addAscendingOrderByColumn('npathlen');
\$criteria->addAscendingOrderByColumn($nodePeerClassname::NPATH_COLNAME);
}
return \$criteria;
}
";
}
protected function addBuildTree(&$script)
{
$peerClassname = $this->getStubPeerBuilder()->getClassname();
$objectClassname = $this->getStubObjectBuilder()->getClassname();
$nodePeerClassname = $this->getStubNodePeerBuilder()->getClassname();
$nodeObjectClassname = $this->getStubNodeBuilder()->getClassname();
$script .= "
/**
* This method reconstructs as much of the tree structure as possible from
* the given array of objects. Depending on how you execute your query, it
* is possible for the ResultSet to contain multiple tree fragments (i.e.
* subtrees). The array returned by this method will contain one entry
* for each subtree root node it finds. The remaining subtree nodes are
* accessible from the $nodeObjectClassname methods of the
* subtree root nodes.
*
* @param array Array of $nodeObjectClassname objects
* @return array Array of $nodeObjectClassname objects
*/
public static function buildTree(\$nodes)
{
// Subtree root nodes to return
\$rootNodes = array();
// Build the tree relations
foreach (\$nodes as \$node)
{
\$sep = strrpos(\$node->getNodePath(), $nodePeerClassname::NPATH_SEP);
\$parentPath = (\$sep !== false ? substr(\$node->getNodePath(), 0, \$sep) : '');
\$parentNode = null;
// Scan other nodes for parent.
foreach (\$nodes as \$pnode)
{
if (\$pnode->getNodePath() === \$parentPath)
{
\$parentNode = \$pnode;
break;
}
}
// If parent was found, attach as child, otherwise its a subtree root
if (\$parentNode)
\$parentNode->attachChildNode(\$node);
else
\$rootNodes[] = \$node;
}
return \$rootNodes;
}
";
}
protected function addPopulateNodes(&$script)
{
$table = $this->getTable();
$peerClassname = $this->getStubPeerBuilder()->getClassname();
$objectClassname = $this->getStubObjectBuilder()->getClassname();
$nodePeerClassname = $this->getStubNodePeerBuilder()->getClassname();
$nodeObjectClassname = $this->getStubNodeBuilder()->getClassname();
$script .= "
/**
* Populates the $objectClassname objects from the
* specified ResultSet, wraps them in $nodeObjectClassname
* objects and build the appropriate node relationships.
* The array returned by this method will only include the initial targets
* of the query, even if ancestors/descendants were also requested.
* The ancestors/descendants will be cached in memory and are accessible via
* the getNode() methods.
*
* @param ResultSet
* @param Criteria
* @return array Array of $nodeObjectClassname objects.
*/
public static function populateNodes(\$rs, \$criteria)
{
\$nodes = array();
\$targets = array();
\$targetfld = count(\$criteria->getSelectColumns());
";
if (!$table->getChildrenColumn()) {
$script .= "
// set the class once to avoid overhead in the loop
\$cls = Propel::import($peerClassname::getOMClass());
";
}
$script .= "
// populate the object(s)
while(\$rs->next())
{
if (!isset(\$nodes[\$rs->getString(1)]))
{
";
if ($table->getChildrenColumn()) {
$script .= "
// class must be set each time from the record row
$cls = Propel::import($peerClassname::getOMClass($rs, 1));
";
}
$script .= "
\$obj = new \$cls();
\$obj->hydrate(\$rs);
\$nodes[\$rs->getString(1)] = new $nodeObjectClassname(\$obj);
}
\$node = \$nodes[\$rs->getString(1)];
if (\$node->getNodePath() === \$rs->getString(\$targetfld))
\$targets[\$node->getNodePath()] = \$node;
}
$nodePeerClassname::buildTree(\$nodes);
return array_values(\$targets);
}
";
}
} // PHP5NodePeerBuilder

View File

@ -0,0 +1,131 @@
<?php
/*
* $Id: DDLBuilder.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/DataModelBuilder.php';
/**
* Baseclass for SQL DDL-building classes.
*
* DDL-building classes are those that build all the SQL DDL for a single table.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql
*/
abstract class DDLBuilder extends DataModelBuilder {
/**
* Builds the SQL for current table and returns it as a string.
*
* This is the main entry point and defines a basic structure that classes should follow.
* In most cases this method will not need to be overridden by subclasses.
*
* @return string The resulting SQL DDL.
*/
public function build()
{
$script = "";
$this->addTable($script);
$this->addIndices($script);
$this->addForeignKeys($script);
return $script;
}
/**
* Builds the DDL SQL for a Column object.
* @return string
*/
public function getColumnDDL(Column $col)
{
$platform = $this->getPlatform();
$domain = $col->getDomain();
$sb = "";
$sb .= $this->quoteIdentifier($col->getName()) . " ";
$sb .= $domain->getSqlType();
if ($platform->hasSize($domain->getSqlType())) {
$sb .= $domain->printSize();
}
$sb .= " ";
$sb .= $col->getDefaultSetting() . " ";
$sb .= $col->getNotNullString() . " ";
$sb .= $col->getAutoIncrementString();
return trim($sb);
}
/**
* Creates a delimiter-delimited string list of column names, quoted using quoteIdentifier().
* @param array Column[] or string[]
* @param string $delim The delimiter to use in separating the column names.
* @return string
*/
public function getColumnList($columns, $delim=',')
{
$list = array();
foreach($columns as $col) {
if ($col instanceof Column) {
$col = $col->getName();
}
$list[] = $this->quoteIdentifier($col);
}
return implode($delim, $list);
}
/**
* This function adds any _database_ start/initialization SQL.
* This is designed to be called for a database, not a specific table, hence it is static.
* @return string The DDL is returned as astring.
*/
public static function getDatabaseStartDDL()
{
return '';
}
/**
* This function adds any _database_ end/cleanup SQL.
* This is designed to be called for a database, not a specific table, hence it is static.
* @return string The DDL is returned as astring.
*/
public static function getDatabaseEndDDL()
{
return '';
}
/**
* Adds table definition.
* @param string &$script The script will be modified in this method.
*/
abstract protected function addTable(&$script);
/**
* Adds index definitions.
* @param string &$script The script will be modified in this method.
*/
abstract protected function addIndices(&$script);
/**
* Adds foreign key constraint definitions.
* @param string &$script The script will be modified in this method.
*/
abstract protected function addForeignKeys(&$script);
}

View File

@ -0,0 +1,215 @@
<?php
/*
* $Id: DataSQLBuilder.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/DataModelBuilder.php';
/**
* Baseclass for SQL data dump SQL building classes.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql
*/
abstract class DataSQLBuilder extends DataModelBuilder {
/**
* The main method in this class, returns the SQL for INSERTing data into a row.
* @param DataRow $row The row to process.
* @return string
*/
public function buildRowSql(DataRow $row)
{
$sql = "";
$platform = $this->getPlatform();
$table = $this->getTable();
$sql .= "INSERT INTO ".$this->quoteIdentifier($this->getTable()->getName())." (";
// add column names to SQL
$colNames = array();
foreach ($row->getColumnValues() as $colValue) {
$colNames[] = $this->quoteIdentifier($colValue->getColumn()->getName());
}
$sql .= implode(',', $colNames);
$sql .= ") VALUES (";
$colVals = array();
foreach ($row->getColumnValues() as $colValue) {
$colVals[] = $this->getColumnValueSql($colValue);
}
$sql .= implode(',', $colVals);
$sql .= ");
";
return $sql;
}
/**
* Gets the propertly escaped (and quoted) value for a column.
* @param ColumnValue $colValue
* @return mixed The proper value to be added to the string.
*/
protected function getColumnValueSql(ColumnValue $colValue)
{
$column = $colValue->getColumn();
$creoleTypeString = PropelTypes::getCreoleType($column->getPropelType());
$creoleTypeCode = CreoleTypes::getCreoleCode($creoleTypeString);
$method = 'get' . CreoleTypes::getAffix($creoleTypeCode) . 'Sql';
return $this->$method($colValue->getValue());
}
/**
* Gets a representation of a binary value suitable for use in a SQL statement.
* Default behavior is true = 1, false = 0.
* @param boolean $value
* @return int
*/
protected function getBooleanSql($value)
{
return (int) $value;
}
/**
* Gets a representation of a BLOB/LONGVARBINARY value suitable for use in a SQL statement.
* @param mixed $blob Blob object or string data.
* @return string
*/
protected function getBlobSql($blob)
{
// they took magic __toString() out of PHP5.0.0; this sucks
if (is_object($blob)) {
return "'" . $this->escape($blob->__toString()) . "'";
} else {
return "'" . $this->escape($blob) . "'";
}
}
/**
* Gets a representation of a CLOB/LONGVARCHAR value suitable for use in a SQL statement.
* @param mixed $clob Clob object or string data.
* @return string
*/
protected function getClobSql($clob)
{
// they took magic __toString() out of PHP5.0.0; this sucks
if (is_object($clob)) {
return "'" . $this->escape($clob->__toString()) . "'";
} else {
return "'" . $this->escape($clob) . "'";
}
}
/**
* Gets a representation of a date value suitable for use in a SQL statement.
* @param string $value
* @return string
*/
protected function getDateSql($value)
{
return "'" . date('Y-m-d', strtotime($value)) . "'";
}
/**
* Gets a representation of a decimal value suitable for use in a SQL statement.
* @param double $value
* @return float
*/
protected function getDecimalSql($value)
{
return (float) $value;
}
/**
* Gets a representation of a double value suitable for use in a SQL statement.
* @param double $value
* @return double
*/
protected function getDoubleSql($value)
{
return (double) $value;
}
/**
* Gets a representation of a float value suitable for use in a SQL statement.
* @param float $value
* @return float
*/
protected function getFloatSql($value)
{
return (float) $value;
}
/**
* Gets a representation of an integer value suitable for use in a SQL statement.
* @param int $value
* @return int
*/
protected function getIntSql($value)
{
return (int) $value;
}
/**
* Gets a representation of a NULL value suitable for use in a SQL statement.
* @return null
*/
protected function getNullSql()
{
return 'NULL';
}
/**
* Gets a representation of a string value suitable for use in a SQL statement.
* @param string $value
* @return string
*/
protected function getStringSql($value)
{
return "'" . $this->getPlatform()->escapeText($value) . "'";
}
/**
* Gets a representation of a time value suitable for use in a SQL statement.
* @param string $value
* @return string
*/
protected function getTimeSql($paramIndex, $value)
{
return "'" . date('H:i:s', strtotime($value)) . "'";
}
/**
* Gets a representation of a timestamp value suitable for use in a SQL statement.
* @param string $value
* @return string
*/
function getTimestampSql($value)
{
return "'" . date('Y-m-d H:i:s', strtotime($value)) . "'";
}
}

View File

@ -0,0 +1,185 @@
<?php
/*
* $Id: MssqlDDLBuilder.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/sql/DDLBuilder.php';
/**
* The SQL DDL-building class for MS SQL Server.
*
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql.pgsql
*/
class MssqlDDLBuilder extends DDLBuilder {
private static $dropCount = 0;
/**
*
* @see parent::addDropStatement()
*/
protected function addDropStatements(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
foreach ($table->getForeignKeys() as $fk) {
$script .= "
IF EXISTS (SELECT 1 FROM sysobjects WHERE type ='RI' AND name='".$fk->getName()."')
ALTER TABLE ".$this->quoteIdentifier($table->getName())." DROP CONSTRAINT ".$this->quoteIdentifier($fk->getName()).";
";
}
self::$dropCount++;
$script .= "
IF EXISTS (SELECT 1 FROM sysobjects WHERE type = 'U' AND name = '".$table->getName()."')
BEGIN
DECLARE @reftable_".self::$dropCount." nvarchar(60), @constraintname_".self::$dropCount." nvarchar(60)
DECLARE refcursor CURSOR FOR
select reftables.name tablename, cons.name constraintname
from sysobjects tables,
sysobjects reftables,
sysobjects cons,
sysreferences ref
where tables.id = ref.rkeyid
and cons.id = ref.constid
and reftables.id = ref.fkeyid
and tables.name = '".$table->getName()."'
OPEN refcursor
FETCH NEXT from refcursor into @reftable_".self::$dropCount.", @constraintname_".self::$dropCount."
while @@FETCH_STATUS = 0
BEGIN
exec ('alter table '+@reftable_".self::$dropCount."+' drop constraint '+@constraintname_".self::$dropCount.")
FETCH NEXT from refcursor into @reftable_".self::$dropCount.", @constraintname_".self::$dropCount."
END
CLOSE refcursor
DEALLOCATE refcursor
DROP TABLE ".$this->quoteIdentifier($table->getName())."
END
";
}
/**
* @see parent::addColumns()
*/
protected function addTable(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
$script .= "
/* ---------------------------------------------------------------------- */
/* ".$table->getName()." */
/* ---------------------------------------------------------------------- */
";
$this->addDropStatements($script);
$script .= "
CREATE TABLE ".$this->quoteIdentifier($table->getName())."
(
";
$lines = array();
foreach ($table->getColumns() as $col) {
$lines[] = $this->getColumnDDL($col);
}
if ($table->hasPrimaryKey()) {
$lines[] = "CONSTRAINT ".$this->quoteIdentifier($table->getName())."_PK PRIMARY KEY (".$this->getColumnList($table->getPrimaryKey()).")";
}
foreach ($table->getUnices() as $unique ) {
$lines[] = "UNIQUE (".$this->getColumnList($unique->getColumns()).")";
}
$sep = ",
";
$script .= implode($sep, $lines);
$script .= "
);
";
}
/**
* Adds CREATE INDEX statements for this table.
* @see parent::addIndices()
*/
protected function addIndices(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
foreach ($table->getIndices() as $index) {
$script .= "
CREATE ";
if($index->getIsUnique()) {
$script .= "UNIQUE";
}
$script .= "INDEX ".$this->quoteIdentifier($index->getName())." ON ".$this->quoteIdentifier($table->getName())." (".$this->getColumnList($index->getColumns()).");
";
}
}
/**
*
* @see parent::addForeignKeys()
*/
protected function addForeignKeys(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
foreach ($table->getForeignKeys() as $fk) {
$script .= "
BEGIN
ALTER TABLE ".$this->quoteIdentifier($table->getName())." ADD CONSTRAINT ".$this->quoteIdentifier($fk->getName())." FOREIGN KEY (".$this->getColumnList($fk->getLocalColumns()) .") REFERENCES ".$this->quoteIdentifier($fk->getForeignTableName())." (".$this->getColumnList($fk->getForeignColumns()).")";
if ($fk->hasOnUpdate()) {
if ($fk->getOnUpdate() == ForeignKey::SETNULL) { // there may be others that also won't work
// we have to skip this because it's unsupported.
$this->warn("MSSQL doesn't support the 'SET NULL' option for ON UPDATE (ignoring for ".$this->getColumnList($fk->getLocalColumns())." fk).");
} else {
$script .= " ON UPDATE ".$fk->getOnUpdate();
}
}
if ($fk->hasOnDelete()) {
if ($fk->getOnDelete() == ForeignKey::SETNULL) { // there may be others that also won't work
// we have to skip this because it's unsupported.
$this->warn("MSSQL doesn't support the 'SET NULL' option for ON DELETE (ignoring for ".$this->getColumnList($fk->getLocalColumns())." fk).");
} else {
$script .= " ON DELETE ".$fk->getOnDelete();
}
}
$script .= "
END
;
";
}
}
}

View File

@ -0,0 +1,48 @@
<?php
/*
* $Id: MssqlDataSQLBuilder.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/sql/DataSQLBuilder.php';
/**
* MS SQL Server class for building data dump SQL.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql.mssql
*/
class MssqlDataSQLBuilder extends DataSQLBuilder {
/**
*
* @param mixed $blob Blob object or string containing data.
* @return string
*/
protected function getBlobSql($blob)
{
// they took magic __toString() out of PHP5.0.0; this sucks
if (is_object($blob)) {
$blob = $blob->__toString();
}
$data = unpack("H*hex", $blob);
return '0x'.$data['hex']; // no surrounding quotes!
}
}

View File

@ -0,0 +1,299 @@
<?php
/*
* $Id: MysqlDDLBuilder.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/sql/DDLBuilder.php';
/**
* DDL Builder class for MySQL.
*
* @author David Z<>lke
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql.mysql
*/
class MysqlDDLBuilder extends DDLBuilder {
/**
* Returns some header SQL that disables foreign key checking.
* @return string DDL
*/
public static function getDatabaseStartDDL()
{
$ddl = "
# This is a fix for InnoDB in MySQL >= 4.1.x
# It \"suspends judgement\" for fkey relationships until are tables are set.
SET FOREIGN_KEY_CHECKS = 0;
";
return $ddl;
}
/**
* Returns some footer SQL that re-enables foreign key checking.
* @return string DDL
*/
public static function getDatabaseEndDDL()
{
$ddl = "
# This restores the fkey checks, after having unset them earlier
SET FOREIGN_KEY_CHECKS = 1;
";
return $ddl;
}
/**
*
* @see parent::addDropStatement()
*/
protected function addDropStatements(&$script)
{
$script .= "
DROP TABLE IF EXISTS ".$this->quoteIdentifier($this->getTable()->getName()).";
";
}
/**
* Builds the SQL for current table and returns it as a string.
*
* This is the main entry point and defines a basic structure that classes should follow.
* In most cases this method will not need to be overridden by subclasses.
*
* @return string The resulting SQL DDL.
*/
public function build()
{
$script = "";
$this->addTable($script);
return $script;
}
/**
*
* @see parent::addColumns()
*/
protected function addTable(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
$script .= "
#-----------------------------------------------------------------------------
#-- ".$table->getName()."
#-----------------------------------------------------------------------------
";
$this->addDropStatements($script);
$script .= "
CREATE TABLE ".$this->quoteIdentifier($table->getName())."
(
";
$lines = array();
foreach ($table->getColumns() as $col) {
$entry = $this->getColumnDDL($col);
if ($col->getDescription()) {
$entry .= " COMMENT '".$platform->escapeText($col->getDescription())."'";
}
$lines[] = $entry;
}
if ($table->hasPrimaryKey()) {
$lines[] = "PRIMARY KEY (".$this->getColumnList($table->getPrimaryKey()).")";
}
$this->addIndicesLines($lines);
$this->addForeignKeysLines($lines);
$sep = ",
";
$script .= implode($sep, $lines);
$script .= "
)";
$mysqlTableType = $this->getBuildProperty("mysqlTableType");
if (!$mysqlTableType) {
$vendorSpecific = $table->getVendorSpecificInfo();
if(isset($vendorSpecific['Type'])) {
$mysqlTableType = $vendorSpecific['Type'];
} else {
$mysqlTableType = 'MyISAM';
}
}
$script .= "Type=$mysqlTableType";
if($table->getDescription()) {
$script .= " COMMENT='".$platform->escapeText($table->getDescription())."'";
}
$script .= ";
";
}
/**
* Creates a comma-separated list of column names for the index.
* For MySQL unique indexes there is the option of specifying size, so we cannot simply use
* the getColumnsList() method.
* @param Index $index
* @return string
*/
private function getIndexColumnList(Index $index)
{
$platform = $this->getPlatform();
$cols = $index->getColumns();
$list = array();
foreach($cols as $col) {
$list[] = $this->quoteIdentifier($col) . ($index->hasColumnSize($col) ? '(' . $index->getColumnSize($col) . ')' : '');
}
return implode(', ', $list);
}
/**
* Adds indexes
*/
protected function addIndicesLines(&$lines)
{
$table = $this->getTable();
$platform = $this->getPlatform();
foreach ($table->getUnices() as $unique) {
$lines[] = "UNIQUE KEY ".$this->quoteIdentifier($unique->getName())." (".$this->getIndexColumnList($unique).")";
}
foreach ($table->getIndices() as $index ) {
$vendor = $index->getVendorSpecificInfo();
$lines[] .= (($vendor && $vendor['Index_type'] == 'FULLTEXT') ? 'FULLTEXT ' : '') . "KEY " . $this->quoteIdentifier($index->getName()) . "(" . $this->getIndexColumnList($index) . ")";
}
}
/**
* Adds foreign key declarations & necessary indexes for mysql (if they don't exist already).
* @see parent::addForeignKeys()
*/
protected function addForeignKeysLines(&$lines)
{
$table = $this->getTable();
$platform = $this->getPlatform();
$_indices = array();
$_previousColumns = array();
// we're building an array of indices here which is smart about multi-column indices.
// for example, if we have to indices foo(ColA) and bar(ColB, ColC), we have actually three indices already defined:
// ColA, ColB+ColC, and ColB (but not ColC!). This is because of the way SQL multi-column indices work.
// we will later match found, defined foreign key and referenced column definitions against this array to know
// whether we should create a new index for mysql or not
foreach($table->getPrimaryKey() as $_primaryKeyColumn) {
// do the above for primary keys
$_previousColumns[] = $this->quoteIdentifier($_primaryKeyColumn->getName());
$_indices[] = implode(',', $_previousColumns);
}
$_tableIndices = array_merge($table->getIndices(), $table->getUnices());
foreach($_tableIndices as $_index) {
// same procedure, this time for unices and indices
$_previousColumns = array();
$_indexColumns = $_index->getColumns();
foreach($_indexColumns as $_indexColumn) {
$_previousColumns[] = $this->quoteIdentifier($_indexColumn);
$_indices[] = implode(',', $_previousColumns);
}
}
// we're determining which tables have foreign keys that point to this table, since MySQL needs an index on
// any column that is referenced by another table (yep, MySQL _is_ a PITA)
$counter = 0;
$allTables = $table->getDatabase()->getTables();
foreach($allTables as $_table) {
foreach($_table->getForeignKeys() as $_foreignKey) {
if($_foreignKey->getForeignTableName() == $table->getName()) {
if(!in_array($this->getColumnList($_foreignKey->getForeignColumns()), $_indices)) {
// no matching index defined in the schema, so we have to create one
$lines[] = "INDEX ".$this->quoteIdentifier("I_referenced_".$_foreignKey->getName()."_".(++$counter))." (" .$this->getColumnList($_foreignKey->getForeignColumns()).")";
}
}
}
}
foreach ($table->getForeignKeys() as $fk) {
$indexName = $this->quoteIdentifier(substr_replace($fk->getName(), 'FI_', strrpos($fk->getName(), 'FK_'), 3));
if(!in_array($this->getColumnList($fk->getLocalColumns()), $_indices)) {
// no matching index defined in the schema, so we have to create one. MySQL needs indices on any columns that serve as foreign keys. these are not auto-created prior to 4.1.2
$lines[] = "INDEX $indexName (".$this->getColumnList($fk->getLocalColumns()).")";
}
$str = "CONSTRAINT ".$this->quoteIdentifier($fk->getName())."
FOREIGN KEY (".$this->getColumnList($fk->getLocalColumns()).")
REFERENCES ".$this->quoteIdentifier($fk->getForeignTableName()) . " (".$this->getColumnList($fk->getForeignColumns()).")";
if ($fk->hasOnUpdate()) {
$str .= "
ON UPDATE ".$fk->getOnUpdate();
}
if ($fk->hasOnDelete()) {
$str .= "
ON DELETE ".$fk->getOnDelete();
}
$lines[] = $str;
}
}
/**
* Checks whether passed-in array of Column objects contains a column with specified name.
* @param array Column[] or string[]
* @param string $searchcol Column name to search for
*/
private function containsColname($columns, $searchcol)
{
foreach($columns as $col) {
if ($col instanceof Column) {
$col = $col->getName();
}
if ($col == $searchcol) {
return true;
}
}
return false;
}
/**
* Not used for MySQL since foreign keys are declared inside table declaration.
* @see addForeignKeysLines()
*/
protected function addForeignKeys(&$script)
{
}
/**
* Not used for MySQL since indexes are declared inside table declaration.
* @see addIndicesLines()
*/
protected function addIndices(&$script)
{
}
}

View File

@ -0,0 +1,33 @@
<?php
/*
* $Id: MysqlDataSQLBuilder.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/sql/DataSQLBuilder.php';
/**
* MySQL class for building data dump SQL.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql.mysql
*/
class MysqlDataSQLBuilder extends DataSQLBuilder {
}

View File

@ -0,0 +1,33 @@
<?php
/*
* $Id: MysqliDDLBuilder.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/sql/mysql/MysqlDDLBuilder.php';
/**
* DDL Builder class for MySQL, specifically using new mysqli API.
*
* @author Hans Lellelid
* @package propel.engine.builder.sql.mysql
*/
class MysqliDDLBuilder extends MysqlDDLBuilder {
}

View File

@ -0,0 +1,33 @@
<?php
/*
* $Id: MysqliDataSQLBuilder.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/sql/DataSQLBuilder.php';
/**
* MySQL class for building data dump SQL.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql.mysql
*/
class MysqliDataSQLBuilder extends DataSQLBuilder {
}

View File

@ -0,0 +1,177 @@
<?php
/*
* $Id: OracleDDLBuilder.php 3754 2007-04-11 09:52:01Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/sql/DDLBuilder.php';
/**
* The SQL DDL-building class for Oracle.
*
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql.pgsql
*/
class OracleDDLBuilder extends DDLBuilder {
/**
*
* @see parent::addDropStatement()
*/
protected function addDropStatements(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
$script .= "
DROP TABLE ".$this->quoteIdentifier($table->getName())." CASCADE CONSTRAINTS;
";
if ($table->getIdMethod() == "native") {
$script .= "
DROP SEQUENCE ".$this->quoteIdentifier($table->getSequenceName()).";
";
}
}
/**
*
* @see parent::addColumns()
*/
protected function addTable(&$script)
{
$table = $this->getTable();
$script .= "
/* -----------------------------------------------------------------------
".$table->getName()."
----------------------------------------------------------------------- */
";
$this->addDropStatements($script);
$script .= "
CREATE TABLE ".$this->quoteIdentifier($table->getName())."
(
";
$lines = array();
foreach ($table->getColumns() as $col) {
$lines[] = $this->getColumnDDL($col);
}
$sep = ",
";
$script .= implode($sep, $lines);
$script .= "
);
";
$this->addPrimaryKey($script);
$this->addIndices($script);
$this->addSequences($script);
}
/**
*
*
*/
protected function addPrimaryKey(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
$tableName = $table->getName();
$length = strlen($tableName);
if ($length > 27) {
$length = 27;
}
if ( is_array($table->getPrimaryKey()) && count($table->getPrimaryKey()) ) {
$script .= "
ALTER TABLE ".$this->quoteIdentifier($table->getName())."
ADD CONSTRAINT ".$this->quoteIdentifier(substr($tableName,0,$length)."_PK")."
PRIMARY KEY (";
$delim = "";
foreach ($table->getPrimaryKey() as $col) {
$script .= $delim . $this->quoteIdentifier($col->getName());
$delim = ",";
}
$script .= ");
";
}
}
/**
* Adds CREATE SEQUENCE statements for this table.
*
*/
protected function addSequences(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
if ($table->getIdMethod() == "native") {
$script .= "CREATE SEQUENCE ".$this->quoteIdentifier($table->getSequenceName())." INCREMENT BY 1 START WITH 1 NOMAXVALUE NOCYCLE NOCACHE ORDER;
";
}
}
/**
* Adds CREATE INDEX statements for this table.
* @see parent::addIndices()
*/
protected function addIndices(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
foreach ($table->getIndices() as $index) {
$script .= "CREATE ";
if($index->getIsUnique()) {
$script .= "UNIQUE";
}
$script .= "INDEX ".$this->quoteIdentifier($index->getName()) ." ON ".$this->quoteIdentifier($table->getName())." (".$this->getColumnList($index->getColumns()).");
";
}
}
/**
*
* @see parent::addForeignKeys()
*/
protected function addForeignKeys(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
foreach ($table->getForeignKeys() as $fk) {
$script .= "
ALTER TABLE ".$this->quoteIdentifier($table->getName())." ADD CONSTRAINT ".$this->quoteIdentifier($fk->getName())." FOREIGN KEY (".$this->getColumnList($fk->getLocalColumns()) .") REFERENCES ".$this->quoteIdentifier($fk->getForeignTableName())." (".$this->getColumnList($fk->getForeignColumns()).")";
if ($fk->hasOnUpdate()) {
$this->warn("ON UPDATE not yet implemented for Oracle builder.(ignoring for ".$this->getColumnList($fk->getLocalColumns())." fk).");
//$script .= " ON UPDATE ".$fk->getOnUpdate();
}
if ($fk->hasOnDelete()) {
$script .= " ON DELETE ".$fk->getOnDelete();
}
$script .= ";
";
}
}
}

View File

@ -0,0 +1,34 @@
<?php
/*
* $Id: OracleDataSQLBuilder.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/sql/DataSQLBuilder.php';
/**
* Oracle class for building data dump SQL.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql.oracle
*/
class OracleDataSQLBuilder extends DataSQLBuilder {
}

View File

@ -0,0 +1,248 @@
<?php
/*
* $Id: PgsqlDDLBuilder.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/sql/DDLBuilder.php';
/**
* The SQL DDL-building class for PostgreSQL.
*
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql.pgsql
*/
class PgsqlDDLBuilder extends DDLBuilder {
/**
* Array that keeps track of already
* added schema names
*
* @var Array of schema names
*/
protected static $addedSchemas = array();
/**
* Get the schema for the current table
*
* @author Markus Lervik <markus.lervik@necora.fi>
* @access protected
* @return schema name if table has one, else
* null
**/
protected function getSchema()
{
$table = $this->getTable();
$schema = $table->getVendorSpecificInfo();
if (!empty($schema) && isset($schema['schema'])) {
return $schema['schema'];
}
return null;
}
/**
* Add a schema to the generated SQL script
*
* @author Markus Lervik <markus.lervik@necora.fi>
* @access protected
* @return string with CREATE SCHEMA statement if
* applicable, else empty string
**/
protected function addSchema()
{
$schemaName = $this->getSchema();
if ($schemaName !== null) {
if (!in_array($schemaName, self::$addedSchemas)) {
$platform = $this->getPlatform();
self::$addedSchemas[] = $schemaName;
return "\nCREATE SCHEMA " . $this->quoteIdentifier($schemaName) . ";\n";
}
}
return '';
}
/**
*
* @see parent::addDropStatement()
*/
protected function addDropStatements(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
$script .= "
DROP TABLE ".$this->quoteIdentifier($table->getName())." CASCADE;
";
if ($table->getIdMethod() == "native") {
$script .= "
DROP SEQUENCE ".$this->quoteIdentifier(strtolower($table->getSequenceName())).";
";
}
}
/**
*
* @see parent::addColumns()
*/
protected function addTable(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
$script .= "
-----------------------------------------------------------------------------
-- ".$table->getName()."
-----------------------------------------------------------------------------
";
$script .= $this->addSchema();
$schemaName = $this->getSchema();
if ($schemaName !== null) {
$script .= "\nSET search_path TO " . $this->quoteIdentifier($schemaName) . ";\n";
}
$this->addDropStatements($script);
$this->addSequences($script);
$script .= "
CREATE TABLE ".$this->quoteIdentifier($table->getName())."
(
";
$lines = array();
foreach ($table->getColumns() as $col) {
$lines[] = $this->getColumnDDL($col);
}
if ($table->hasPrimaryKey()) {
$lines[] = "PRIMARY KEY (".$this->getColumnList($table->getPrimaryKey()).")";
}
foreach ($table->getUnices() as $unique ) {
$lines[] = "CONSTRAINT ".$this->quoteIdentifier($unique->getName())." UNIQUE (".$this->getColumnList($unique->getColumns()).")";
}
$sep = ",
";
$script .= implode($sep, $lines);
$script .= "
);
COMMENT ON TABLE ".$this->quoteIdentifier($table->getName())." IS '" . $platform->escapeText($table->getDescription())."';
";
$this->addColumnComments($script);
$script .= "\nSET search_path TO public;";
}
/**
* Adds comments for the columns.
*
*/
protected function addColumnComments(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
foreach ($this->getTable()->getColumns() as $col) {
if( $col->getDescription() != '' ) {
$script .= "
COMMENT ON COLUMN ".$this->quoteIdentifier($table->getName()).".".$this->quoteIdentifier($col->getName())." IS '".$platform->escapeText($col->getDescription()) ."';
";
}
}
}
/**
* Adds CREATE SEQUENCE statements for this table.
*
*/
protected function addSequences(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
if ($table->getIdMethod() == "native") {
$script .= "
CREATE SEQUENCE ".$this->quoteIdentifier(strtolower($table->getSequenceName())).";
";
}
}
/**
* Adds CREATE INDEX statements for this table.
* @see parent::addIndices()
*/
protected function addIndices(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
foreach ($table->getIndices() as $index) {
$script .= "
CREATE ";
if($index->getIsUnique()) {
$script .= "UNIQUE";
}
$script .= "INDEX ".$this->quoteIdentifier($index->getName())." ON ".$this->quoteIdentifier($table->getName())." (".$this->getColumnList($index->getColumns()).");
";
}
}
/**
*
* @see parent::addForeignKeys()
*/
protected function addForeignKeys(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
foreach ($table->getForeignKeys() as $fk) {
$script .= "
ALTER TABLE ".$this->quoteIdentifier($table->getName())." ADD CONSTRAINT ".$this->quoteIdentifier($fk->getName())." FOREIGN KEY (".$this->getColumnList($fk->getLocalColumns()) .") REFERENCES ".$this->quoteIdentifier($fk->getForeignTableName())." (".$this->getColumnList($fk->getForeignColumns()).")";
if ($fk->hasOnUpdate()) {
$script .= " ON UPDATE ".$fk->getOnUpdate();
}
if ($fk->hasOnDelete()) {
$script .= " ON DELETE ".$fk->getOnDelete();
}
$script .= ";
";
}
}
}

View File

@ -0,0 +1,60 @@
<?php
/*
* $Id: PgsqlDataSQLBuilder.php 3754 2007-04-11 09:52:01Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/sql/DataSQLBuilder.php';
/**
* PostgreSQL class for building data dump SQL.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql.pgsql
*/
class PgsqlDataSQLBuilder extends DataSQLBuilder {
/**
* Get SQL value to insert for Postgres BOOLEAN column.
* @param boolean $value
* @return string The representation of boolean for Postgres ('t' or 'f').
*/
protected function getBooleanSql($value)
{
if ($value === 'f' || $value === 'false' || $value === "0") {
$value = false;
}
return ($value ? "'t'" : "'f'");
}
/**
*
* @param mixed $blob Blob object or string containing data.
* @return string
*/
protected function getBlobSql($blob)
{
// they took magic __toString() out of PHP5.0.0; this sucks
if (is_object($blob)) {
$blob = $blob->__toString();
}
return "'" . pg_escape_bytea($blob) . "'";
}
}

View File

@ -0,0 +1,126 @@
<?php
/*
* $Id: SqliteDDLBuilder.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/sql/DDLBuilder.php';
/**
* The SQL DDL-building class for SQLite.
*
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql.pgsql
*/
class SqliteDDLBuilder extends DDLBuilder {
/**
*
* @see parent::addDropStatement()
*/
protected function addDropStatements(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
$script .= "
DROP TABLE ".$this->quoteIdentifier($table->getName()).";
";
}
/**
*
* @see parent::addColumns()
*/
protected function addTable(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
$script .= "
-----------------------------------------------------------------------------
-- ".$table->getName()."
-----------------------------------------------------------------------------
";
$this->addDropStatements($script);
$script .= "
CREATE TABLE ".$this->quoteIdentifier($table->getName())."
(
";
$lines = array();
foreach ($table->getColumns() as $col) {
$lines[] = $this->getColumnDDL($col);
}
foreach ($table->getUnices() as $unique ) {
$lines[] = "UNIQUE (".$this->getColumnList($unique->getColumns()).")";
}
$sep = ",
";
$script .= implode($sep, $lines);
$script .= "
);
";
}
/**
* Adds CREATE INDEX statements for this table.
* @see parent::addIndices()
*/
protected function addIndices(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
foreach ($table->getIndices() as $index) {
$script .= "
CREATE ";
if($index->getIsUnique()) {
$script .= "UNIQUE";
}
$script .= "INDEX ".$this->quoteIdentifier($index->getName())." ON ".$this->quoteIdentifier($table->getName())." (".$this->getColumnList($index->getColumns()).");
";
}
}
/**
*
* @see parent::addForeignKeys()
*/
protected function addForeignKeys(&$script)
{
$table = $this->getTable();
$platform = $this->getPlatform();
foreach ($table->getForeignKeys() as $fk) {
$script .= "
-- SQLite does not support foreign keys; this is just for reference
-- FOREIGN KEY (".$this->getColumnList($fk->getLocalColumns()).") REFERENCES ".$fk->getForeignTableName()." (".$this->getColumnList($fk->getForeignColumns()).")
";
}
}
}

View File

@ -0,0 +1,47 @@
<?php
/*
* $Id: SqliteDataSQLBuilder.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/builder/sql/DataSQLBuilder.php';
/**
* SQLite class for building data dump SQL.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.engine.builder.sql.sqlite
*/
class SqliteDataSQLBuilder extends DataSQLBuilder {
/**
* Returns string processed by sqlite_udf_encode_binary() to ensure that binary contents will be handled correctly by sqlite.
* @param mixed $blob Blob or string
* @return string encoded text
*/
protected function getBlobSql($blob)
{
// they took magic __toString() out of PHP5.0.0; this sucks
if (is_object($blob)) {
$blob = $blob->__toString();
}
return "'" . sqlite_udf_encode_binary($blob) . "'";
}
}

View File

@ -0,0 +1,206 @@
<?php
/*
* $Id: AppData.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
include_once 'propel/engine/EngineException.php';
include_once 'propel/engine/database/model/Database.php';
/**
* A class for holding application data structures.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Leon Messerschmidt <leon@opticode.co.za> (Torque)
* @author John McNally <jmcnally@collab.net> (Torque)
* @author Daniel Rall <dlr@finemaltcoding.com> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class AppData {
/**
* The list of databases for this application.
* @var array Database[]
*/
private $dbList = array();
/**
* The platform class for our database(s).
* @var string
*/
private $platform;
/**
* Name of the database. Only one database definition
* is allowed in one XML descriptor.
*/
private $name;
/**
* Flag to ensure that initialization is performed only once.
* @var boolean
*/
private $isInitialized = false;
/**
* Creates a new instance for the specified database type.
*
* @param Platform $platform The platform class to use for any databases added to this application model.
*/
public function __construct(Platform $platform)
{
$this->platform = $platform;
}
/**
* Set the name of the database.
*
* @param name of the database.
*/
public function setName($name)
{
$this->name = $name;
}
/**
* Get the name of the database.
*
* @return String name
*/
public function getName()
{
return $this->name;
}
/**
* Get the short name of the database (without the '-schema' postfix).
*
* @return String name
*/
public function getShortName()
{
return str_replace("-schema", "", $name);
}
/**
* Return an array of all databases
*
* @return Array of Database objects
*/
public function getDatabases($doFinalInit = true)
{
// this is temporary until we'll have a clean solution
// for packaging datamodels/requiring schemas
if ($doFinalInit) {
$this->doFinalInitialization();
}
return $this->dbList;
}
/**
* Returns whether this application has multiple databases.
*
* @return boolean True if the application has multiple databases
*/
public function hasMultipleDatabases()
{
return (count($this->dbList) > 1);
}
/**
* Return the database with the specified name.
*
* @param name database name
* @return A Database object. If it does not exist it returns null
*/
public function getDatabase($name = null, $doFinalInit = true)
{
// this is temporary until we'll have a clean solution
// for packaging datamodels/requiring schemas
if ($doFinalInit) {
$this->doFinalInitialization();
}
if ($name === null) {
return $this->dbList[0];
}
for($i=0,$size=count($this->dbList); $i < $size; $i++) {
$db = $this->dbList[$i];
if ($db->getName() === $name) {
return $db;
}
}
return null;
}
/**
* Add a database to the list and sets the AppData property to this
* AppData
*
* @param db the database to add
*/
public function addDatabase($db)
{
if ($db instanceof Database) {
$db->setAppData($this);
if ($db->getPlatform() === null) {
$db->setPlatform($this->platform);
}
$this->dbList[] = $db;
return $db;
} else {
// XML attributes array / hash
$d = new Database();
$d->loadFromXML($db);
return $this->addDatabase($d); // calls self w/ different param type
}
}
/**
*
* @return void
*/
private function doFinalInitialization()
{
if (!$this->isInitialized) {
for($i=0, $size=count($this->dbList); $i < $size; $i++) {
$this->dbList[$i]->doFinalInitialization();
}
$this->isInitialized = true;
}
}
/**
* Creats a string representation of this AppData.
* The representation is given in xml format.
*
* @return string Representation in xml format
*/
public function toString()
{
$result = "<app-data>\n";
for ($i=0,$size=count($this->dbList); $i < $size; $i++) {
$result .= $this->dbList[$i]->toString();
}
$result .= "</app-data>";
return $result;
}
}

View File

@ -0,0 +1,921 @@
<?php
/*
* $Id: Column.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/database/model/XMLElement.php';
include_once 'propel/engine/EngineException.php';
include_once 'propel/engine/database/model/PropelTypes.php';
include_once 'propel/engine/database/model/Inheritance.php';
include_once 'propel/engine/database/model/Domain.php';
/**
* A Class for holding data about a column used in an Application.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Leon Messerschmidt <leon@opticode.co.za> (Torque)
* @author Jason van Zyl <jvanzyl@apache.org> (Torque)
* @author Jon S. Stevens <jon@latchkey.com> (Torque)
* @author Daniel Rall <dlr@finemaltcoding.com> (Torque)
* @author Byron Foster <byron_foster@yahoo.com> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class Column extends XMLElement {
const DEFAULT_TYPE = "VARCHAR";
private $name;
private $description;
private $phpName = null;
private $phpNamingMethod;
private $isNotNull = false;
private $size;
/**
* The name to use for the Peer constant that identifies this column.
* (Will be converted to all-uppercase in the templates.)
* @var string
*/
private $peerName;
/**
* Type as defined in schema.xml
* @var string
*/
private $propelType;
/**
* Type corresponding to Creole type
* @var int
*/
private $creoleType;
/**
* Native PHP type
* @var string "string", "boolean", "int", "double"
*/
private $phpType;
private $parentTable;
private $position;
private $isPrimaryKey = false;
private $isNodeKey = false;
private $nodeKeySep;
private $isUnique = false;
private $isAutoIncrement = false;
private $isLazyLoad = false;
private $defaultValue;
private $referrers;
// only one type is supported currently, which assumes the
// column either contains the classnames or a key to
// classnames specified in the schema. Others may be
// supported later.
private $inheritanceType;
private $isInheritance;
private $isEnumeratedClasses;
private $inheritanceList;
private $needsTransactionInPostgres; //maybe this can be retrieved from vendorSpecificInfo
/** class name to do input validation on this column */
private $inputValidator = null;
private $domain;
/**
* Creates a new column and set the name
*
* @param name column name
*/
public function __construct($name = null)
{
$this->name = $name;
}
/**
* Return a comma delimited string listing the specified columns.
*
* @param columns Either a list of <code>Column</code> objects, or
* a list of <code>String</code> objects with column names.
* @deprecated Use the DDLBuilder->getColumnList() method instead; this will be removed in 1.3
*/
public static function makeList($columns, Platform $platform)
{
$list = array();
foreach($columns as $col) {
if ($col instanceof Column) {
$col = $col->getName();
}
$list[] = $platform->quoteIdentifier($col);
}
return implode(", ", $list);
}
/**
* Sets up the Column object based on the attributes that were passed to loadFromXML().
* @see parent::loadFromXML()
*/
protected function setupObject()
{
try {
$dom = $this->getAttribute("domain");
if ($dom) {
$this->domain = new Domain();
$this->domain->copy($this->getTable()->getDatabase()->getDomain($dom));
} else {
$this->domain = new Domain();
$this->domain->copy($this->getPlatform()->getDomainForType(self::DEFAULT_TYPE));
$this->setType(strtoupper($this->getAttribute("type")));
}
//Name
$this->name = $this->getAttribute("name");
$this->phpName = $this->getAttribute("phpName");
$this->phpType = $this->getAttribute("phpType");
$this->peerName = $this->getAttribute("peerName");
if (empty($this->phpType)) {
$this->phpType = null;
}
// retrieves the method for converting from specified name to
// a PHP name.
$this->phpNamingMethod = $this->getAttribute("phpNamingMethod", $this->parentTable->getDatabase()->getDefaultPhpNamingMethod());
$this->isPrimaryKey = $this->booleanValue($this->getAttribute("primaryKey"));
$this->isNodeKey = $this->booleanValue($this->getAttribute("nodeKey"));
$this->nodeKeySep = $this->getAttribute("nodeKeySep", ".");
$this->isNotNull = $this->booleanValue($this->getAttribute("required"), false);
// Regardless of above, if this column is a primary key then it can't be null.
if ($this->isPrimaryKey) {
$this->isNotNull = true;
}
//AutoIncrement/Sequences
$this->isAutoIncrement = $this->booleanValue($this->getAttribute("autoIncrement"));
$this->isLazyLoad = $this->booleanValue($this->getAttribute("lazyLoad"));
//Default column value.
$this->domain->replaceDefaultValue($this->getAttribute("default"));
$this->domain->replaceSize($this->getAttribute("size"));
$this->domain->replaceScale($this->getAttribute("scale"));
$this->inheritanceType = $this->getAttribute("inheritance");
$this->isInheritance = ($this->inheritanceType !== null
&& $this->inheritanceType !== "false"); // here we are only checking for 'false', so don't
// use boleanValue()
$this->inputValidator = $this->getAttribute("inputValidator");
$this->description = $this->getAttribute("description");
} catch (Exception $e) {
throw new EngineException("Error setting up column " . var_export($this->getAttribute("name"), true) . ": " . $e->getMessage());
}
}
/**
* Gets domain for this column.
* @return Domain
*/
public function getDomain()
{
return $this->domain;
}
/**
* Returns table.column
*/
public function getFullyQualifiedName()
{
return ($this->parentTable->getName() . '.' . name);
}
/**
* Get the name of the column
*/
public function getName()
{
return $this->name;
}
/**
* Set the name of the column
*/
public function setName($newName)
{
$this->name = $newName;
}
/**
* Get the description for the Table
*/
public function getDescription()
{
return $this->description;
}
/**
* Set the description for the Table
*
* @param newDescription description for the Table
*/
public function setDescription($newDescription)
{
$this->description = $newDescription;
}
/**
* Get name to use in PHP sources
* @return string
*/
public function getPhpName()
{
if ($this->phpName === null) {
$inputs = array();
$inputs[] = $this->name;
$inputs[] = $this->phpNamingMethod;
try {
$this->phpName = NameFactory::generateName(NameFactory::PHP_GENERATOR, $inputs);
} catch (EngineException $e) {
print $e->getMessage() . "\n";
print $e->getTraceAsString();
}
}
return $this->phpName;
}
/**
* Set name to use in PHP sources
*/
public function setPhpName($phpName)
{
$this->phpName = $phpName;
}
/**
* Get the Peer constant name that will identify this column.
* @return string
*/
public function getPeerName() {
return $this->peerName;
}
/**
* Set the Peer constant name that will identify this column.
* @param $name string
*/
public function setPeerName($name) {
$this->peerName = $name;
}
/**
* Get type to use in PHP sources.
* If no type has been specified, then uses results
* of getPhpNative().
*
* The distinction between getPhpType() and getPhpNative()
* is not as salient in PHP as it is in Java, but we'd like to leave open the
* option of specifying complex types (objects) in the schema. While we can
* always cast to PHP native types, we can't cast objects (in PHP) -- hence the
* importance of maintaining this distinction.
*
* @return string The type name.
* @see getPhpNative()
*/
public function getPhpType()
{
if ($this->phpType !== null) {
return $this->phpType;
}
return $this->getPhpNative();
}
/**
* Get the location of this column within the table (one-based).
* @return int value of position.
*/
public function getPosition()
{
return $this->position;
}
/**
* Get the location of this column within the table (one-based).
* @param int $v Value to assign to position.
*/
public function setPosition($v)
{
$this->position = $v;
}
/**
* Set the parent Table of the column
*/
public function setTable(Table $parent)
{
$this->parentTable = $parent;
}
/**
* Get the parent Table of the column
*/
public function getTable()
{
return $this->parentTable;
}
/**
* Returns the Name of the table the column is in
*/
public function getTableName()
{
return $this->parentTable->getName();
}
/**
* Adds a new inheritance definition to the inheritance list and set the
* parent column of the inheritance to the current column
* @param mixed $inhdata Inheritance or XML data.
*/
public function addInheritance($inhdata)
{
if ($inhdata instanceof Inheritance) {
$inh = $inhdata;
$inh->setColumn($this);
if ($this->inheritanceList === null) {
$this->inheritanceList = array();
$this->isEnumeratedClasses = true;
}
$this->inheritanceList[] = $inh;
return $inh;
} else {
$inh = new Inheritance();
$inh->loadFromXML($inhdata);
return $this->addInheritance($inh);
}
}
/**
* Get the inheritance definitions.
*/
public function getChildren()
{
return $this->inheritanceList;
}
/**
* Determine if this column is a normal property or specifies a
* the classes that are represented in the table containing this column.
*/
public function isInheritance()
{
return $this->isInheritance;
}
/**
* Determine if possible classes have been enumerated in the xml file.
*/
public function isEnumeratedClasses()
{
return $this->isEnumeratedClasses;
}
/**
* Return the isNotNull property of the column
*/
public function isNotNull()
{
return $this->isNotNull;
}
/**
* Set the isNotNull property of the column
*/
public function setNotNull($status)
{
$this->isNotNull = (boolean) $status;
}
/**
* Return NOT NULL String for this column
*
* @return "NOT NULL" if null values are not allowed or an empty string.
*/
public function getNotNullString()
{
return $this->getTable()->getDatabase()->getPlatform()->getNullString($this->isNotNull());
}
/**
* Set if the column is a primary key or not
*/
public function setPrimaryKey($pk)
{
$this->isPrimaryKey = (boolean) $pk;
}
/**
* Return true if the column is a primary key
*/
public function isPrimaryKey()
{
return $this->isPrimaryKey;
}
/**
* Set if the column is the node key of a tree
*/
public function setNodeKey($nk)
{
$this->isNodeKey = (boolean) $nk;
}
/**
* Return true if the column is a node key of a tree
*/
public function isNodeKey()
{
return $this->isNodeKey;
}
/**
* Set if the column is the node key of a tree
*/
public function setNodeKeySep($sep)
{
$this->nodeKeySep = (string) $sep;
}
/**
* Return true if the column is a node key of a tree
*/
public function getNodeKeySep()
{
return $this->nodeKeySep;
}
/**
* Set true if the column is UNIQUE
*/
public function setUnique($u)
{
$this->isUnique = $u;
}
/**
* Get the UNIQUE property
*/
public function isUnique()
{
return $this->isUnique;
}
/**
* Return true if the column requires a transaction in Postgres
*/
public function requiresTransactionInPostgres()
{
return $this->needsTransactionInPostgres;
}
/**
* Utility method to determine if this column is a foreign key.
*/
public function isForeignKey()
{
return ($this->getForeignKey() !== null);
}
/**
* Determine if this column is a foreign key that refers to the
* same table as another foreign key column in this table.
*/
public function isMultipleFK()
{
$fk = $this->getForeignKey();
if ($fk !== null) {
$fks = $this->parentTable->getForeignKeys();
for ($i=0, $len=count($fks); $i < $len; $i++) {
if ($fks[$i]->getForeignTableName() === $fk->getForeignTableName()
&& !in_array($this->name, $fks[$i]->getLocalColumns()) ) {
return true;
}
}
}
// No multiple foreign keys.
return false;
}
/**
* get the foreign key object for this column
* if it is a foreign key or part of a foreign key
*/
public function getForeignKey()
{
return $this->parentTable->getForeignKey($this->name);
}
/**
* Utility method to get the related table of this column if it is a foreign
* key or part of a foreign key
*/
public function getRelatedTableName()
{
$fk = $this->getForeignKey();
return ($fk === null ? null : $fk->getForeignTableName());
}
/**
* Utility method to get the related column of this local column if this
* column is a foreign key or part of a foreign key.
*/
public function getRelatedColumnName()
{
$fk = $this->getForeignKey();
if ($fk === null) {
return null;
} else {
$m = $fk->getLocalForeignMapping();
$c = @$m[$this->name];
if ($c === null) {
return null;
} else {
return $c;
}
}
}
/**
* Adds the foreign key from another table that refers to this column.
*/
public function addReferrer(ForeignKey $fk)
{
if ($this->referrers === null) {
$this->referrers = array();
}
$this->referrers[] = $fk;
}
/**
* Get list of references to this column.
*/
public function getReferrers()
{
if ($this->referrers === null) {
$this->referrers = array();
}
return $this->referrers;
}
/**
* Returns the colunm type
*/
public function setType($propelType)
{
$this->domain = new Domain();
$this->domain->copy($this->getPlatform()->getDomainForType($propelType));
$this->propelType = $propelType;
if ($propelType == PropelTypes::VARBINARY|| $propelType == PropelTypes::LONGVARBINARY || $propelType == PropelTypes::BLOB) {
$this->needsTransactionInPostgres = true;
}
}
/**
* Returns the column Creole type as a string.
* @return string The constant representing Creole type: e.g. "VARCHAR".
*/
public function getType()
{
return PropelTypes::getCreoleType($this->propelType);
}
/**
* Returns the column type as given in the schema as an object
*/
public function getPropelType()
{
return $this->propelType;
}
/**
* Utility method to know whether column needs Blob/Lob handling.
* @return boolean
*/
public function isLob()
{
return PropelTypes::isLobType($this->propelType);
}
/**
* Utility method to see if the column is a string
*/
public function isString()
{
return PropelTypes::isTextxType($this->propelType);
}
/**
* String representation of the column. This is an xml representation.
*/
public function toString()
{
$result = " <column name=\"" . $this->name . '"';
if ($this->phpName !== null) {
$result .= " phpName=\"" . $this->phpName . '"';
}
if ($this->isPrimaryKey) {
$result .= " primaryKey=\"" . ($this->isPrimaryKey ? "true" : "false"). '"';
}
if ($this->isNotNull) {
$result .= " required=\"true\"";
} else {
$result .= " required=\"false\"";
}
$result .= " type=\"" . $this->propelType . '"';
if ($this->domain->getSize() !== null) {
$result .= " size=\"" . $this->domain->getSize() . '"';
}
if ($this->domain->getScale() !== null) {
$result .= " scale=\"" . $this->domain->getScale() . '"';
}
if ($this->domain->getDefaultValue() !== null) {
$result .= " default=\"" . $this->domain->getDefaultValue() . '"';
}
if ($this->isInheritance()) {
$result .= " inheritance=\"" . $this->inheritanceType
. '"';
}
if ($this->isNodeKey()) {
$result .= " nodeKey=\"true\"";
if ($this->getNodeKeySep() !== null) {
$result .= " nodeKeySep=\"" . $this->nodeKeySep . '"';
}
}
// Close the column.
$result .= " />\n";
return $result;
}
/**
* Returns the size of the column
* @return string
*/
public function getSize()
{
return $this->domain->getSize();
}
/**
* Set the size of the column
* @param string $newSize
*/
public function setSize($newSize)
{
$this->domain->setSize($newSize);
}
/**
* Returns the scale of the column
* @return string
*/
public function getScale()
{
return $this->domain->getScale();
}
/**
* Set the scale of the column
* @param string $newScale
*/
public function setScale($newScale)
{
$this->domain->setScale($newScale);
}
/**
* Return the size in brackets for use in an sql
* schema if the type is String. Otherwise return an empty string
*/
public function printSize()
{
return $this->domain->printSize();
}
/**
* Return a string that will give this column a default value.
* @return string
*/
public function getDefaultSetting()
{
$dflt = "";
if ($this->getDefaultValue() !== null) {
$dflt .= "default ";
if (PropelTypes::isTextType($this->getType())) {
$dflt .= '\'' . $this->getPlatform()->escapeText($this->getDefaultValue()) . '\'';
} elseif ($this->getType() == PropelTypes::BOOLEAN) {
$dflt .= $this->getPlatform()->getBooleanString($this->getDefaultValue());
} else {
$dflt .= $this->getDefaultValue();
}
}
return $dflt;
}
/**
* Set a string that will give this column a default value.
*/
public function setDefaultValue($def)
{
$this->domain->setDefaultValue($def);
}
/**
* Get the raw string that will give this column a default value.
* @return string
* @see Domain::getDefaultValue()
*/
public function getDefaultValue()
{
return $this->domain->getDefaultValue();
}
/**
* Get the default value suitable for use in PHP.
* @return mixed
* @see Domain::getPhpDefaultValue()
*/
public function getPhpDefaultValue()
{
return $this->domain->getPhpDefaultValue();
}
/**
* Returns the class name to do input validation
*/
public function getInputValidator()
{
return $this->inputValidator;
}
/**
* Return auto increment/sequence string for the target database. We need to
* pass in the props for the target database!
*/
public function isAutoIncrement()
{
return $this->isAutoIncrement;
}
/**
* Return auto increment/sequence string for the target database. We need to
* pass in the props for the target database!
*/
public function isLazyLoad()
{
return $this->isLazyLoad;
}
/**
* Gets the auto-increment string.
* @return string
*/
public function getAutoIncrementString()
{
if ($this->isAutoIncrement()&& IDMethod::NATIVE === $this->getTable()->getIdMethod()) {
return $this->getPlatform()->getAutoIncrement();
} elseif ($this->isAutoIncrement()) {
throw new EngineException("You have specified autoIncrement for column '" . $this->name . "' but you have not specified idMethod=\"native\" for table '" . $this->getTable()->getName() . "'.");
}
return "";
}
/**
* Set the auto increment value.
* Use isAutoIncrement() to find out if it is set or not.
*/
public function setAutoIncrement($value)
{
$this->isAutoIncrement = (boolean) $value;
}
/**
* Set the column type from a string property
* (normally a string from an sql input file)
*/
public function setTypeFromString($typeName, $size)
{
$tn = strtoupper($typeName);
$this->setType($tn);
if ($size !== null) {
$this->size = $size;
}
if (strpos($tn, "CHAR") !== false) {
$this->domain->setType(PropelTypes::VARCHAR);
} elseif (strpos($tn, "INT") !== false) {
$this->domain->setType(PropelTypes::INTEGER);
} elseif (strpos($tn, "FLOAT") !== false) {
$this->domain->setType(PropelTypes::FLOAT);
} elseif (strpos($tn, "DATE") !== false) {
$this->domain->setType(PropelTypes::DATE);
} elseif (strpos($tn, "TIME") !== false) {
$this->domain->setType(PropelTypes::TIMESTAMP);
} else if (strpos($tn, "BINARY") !== false) {
$this->domain->setType(PropelTypes::LONGVARBINARY);
} else {
$this->domain->setType(PropelTypes::VARCHAR);
}
}
/**
* Return a string representation of the native PHP type which corresponds
* to the Creole type of this column. Use in the generation of Base objects.
*
* @return string PHP datatype used by propel.
*/
public function getPhpNative()
{
return PropelTypes::getPHPNative($this->propelType);
}
/**
* Returns true if the column's PHP native type is an
* boolean, int, long, float, double, string
*/
public function isPrimitive()
{
$t = $this->getPhpNative();
return in_array($t, array("boolean", "int", "double", "string"));
}
/**
* Return true if column's PHP native type is an
* boolean, int, long, float, double
*/
public function isPrimitiveNumeric()
{
$t = $this->getPhpNative();
return in_array($t, array("boolean", "int", "double"));
}
/**
* Get the platform/adapter impl.
*
* @return Platform
*/
public function getPlatform()
{
return $this->getTable()->getDatabase()->getPlatform();
}
/**
*
* @return string
* @deprecated Use DDLBuilder->getColumnDDL() instead; this will be removed in 1.3
*/
public function getSqlString()
{
$sb = "";
$sb .= $this->getPlatform()->quoteIdentifier($this->getName()) . " ";
$sb .= $this->getDomain()->getSqlType();
if ($this->getPlatform()->hasSize($this->getDomain()->getSqlType())) {
$sb .= $this->getDomain()->printSize();
}
$sb .= " ";
$sb .= $this->getDefaultSetting() . " ";
$sb .= $this->getNotNullString() . " ";
$sb .= $this->getAutoIncrementString();
return trim($sb);
}
}

View File

@ -0,0 +1,84 @@
<?php
/*
* $Id: ConstraintNameGenerator.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
/**
* A <code>NameGenerator</code> implementation for table-specific
* constraints. Conforms to the maximum column name length for the
* type of database in use.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Daniel Rall <dlr@finemaltcoding.com> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class ConstraintNameGenerator implements NameGenerator {
/**
* Conditional compilation flag.
*/
const DEBUG = false;
/**
* First element of <code>inputs</code> should be of type {@link Database}, second
* should be a table name, third is the type identifier (spared if
* trimming is necessary due to database type length constraints),
* and the fourth is a <code>Integer</code> indicating the number
* of this contraint.
*
* @see NameGenerator
* @throws EngineException
*/
public function generateName($inputs)
{
$db = $inputs[0];
$name = $inputs[1];
$namePostfix = $inputs[2];
$constraintNbr = (string) $inputs[3];
// Calculate maximum RDBMS-specific column character limit.
$maxBodyLength = -1;
try {
$maxColumnNameLength = (int) $db->getPlatform()->getMaxColumnNameLength();
$maxBodyLength = ($maxColumnNameLength - strlen($namePostfix)
- strlen($constraintNbr) - 2);
if (self::DEBUG) {
print("maxColumnNameLength=" . $maxColumnNameLength
. " maxBodyLength=" . $maxBodyLength . "\n");
}
} catch (EngineException $e) {
echo $e;
throw $e;
}
// Do any necessary trimming.
if ($maxBodyLength !== -1 && strlen($name) > $maxBodyLength) {
$name = substr($name, 0, $maxBodyLength);
}
$name .= self::STD_SEPARATOR_CHAR . $namePostfix
. self::STD_SEPARATOR_CHAR . $constraintNbr;
return $name;
}
}

View File

@ -0,0 +1,463 @@
<?php
/*
* $Id: Database.php 576 2007-02-09 19:08:40Z hans $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/database/model/XMLElement.php';
include_once 'propel/engine/database/model/IDMethod.php';
include_once 'propel/engine/database/model/NameGenerator.php';
include_once 'propel/engine/database/model/Table.php';
/**
* A class for holding application data structures.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Leon Messerschmidt <leon@opticode.co.za> (Torque)
* @author John McNally<jmcnally@collab.net> (Torque)
* @author Martin Poeschl<mpoeschl@marmot.at> (Torque)
* @author Daniel Rall<dlr@collab.net> (Torque)
* @author Byron Foster <byron_foster@yahoo.com> (Torque)
* @version $Revision: 576 $
* @package propel.engine.database.model
*/
class Database extends XMLElement {
private $platform;
private $tableList = array();
private $curColumn;
private $name;
private $pkg;
private $baseClass;
private $basePeer;
private $defaultIdMethod;
private $defaultPhpType;
private $defaultPhpNamingMethod;
private $defaultTranslateMethod;
private $dbParent;
private $tablesByName = array();
private $tablesByPhpName = array();
private $heavyIndexing;
private $domainMap = array();
/**
* Sets up the Database object based on the attributes that were passed to loadFromXML().
* @see parent::loadFromXML()
*/
protected function setupObject()
{
$this->name = $this->getAttribute("name");
$this->pkg = $this->getAttribute("package");
$this->baseClass = $this->getAttribute("baseClass");
$this->basePeer = $this->getAttribute("basePeer");
$this->defaultPhpType = $this->getAttribute("defaultPhpType");
$this->defaultIdMethod = $this->getAttribute("defaultIdMethod");
$this->defaultPhpNamingMethod = $this->getAttribute("defaultPhpNamingMethod", NameGenerator::CONV_METHOD_UNDERSCORE);
$this->defaultTranslateMethod = $this->getAttribute("defaultTranslateMethod", Validator::TRANSLATE_NONE);
$this->heavyIndexing = $this->booleanValue($this->getAttribute("heavyIndexing"));
}
/**
* Returns the Platform implementation for this database.
*
* @return Platform a Platform implementation
*/
public function getPlatform()
{
return $this->platform;
}
/**
* Sets the Platform implementation for this database.
*
* @param Platform $platform A Platform implementation
*/
public function setPlatform($platform)
{
$this->platform = $platform;
}
/**
* Get the name of the Database
*/
public function getName()
{
return $this->name;
}
/**
* Set the name of the Database
*/
public function setName($name)
{
$this->name = $name;
}
/**
* Get the value of package.
* @return value of package.
*/
public function getPackage()
{
return $this->pkg;
}
/**
* Set the value of package.
* @param v Value to assign to package.
*/
public function setPackage($v)
{
$this->pkg = $v;
}
/**
* Get the value of baseClass.
* @return value of baseClass.
*/
public function getBaseClass()
{
return $this->baseClass;
}
/**
* Set the value of baseClass.
* @param v Value to assign to baseClass.
*/
public function setBaseClass($v)
{
$this->baseClass = $v;
}
/**
* Get the value of basePeer.
* @return value of basePeer.
*/
public function getBasePeer()
{
return $this->basePeer;
}
/**
* Set the value of basePeer.
* @param v Value to assign to basePeer.
*/
public function setBasePeer($v)
{
$this->basePeer = $v;
}
/**
* Get the value of defaultIdMethod.
* @return value of defaultIdMethod.
*/
public function getDefaultIdMethod()
{
return $this->defaultIdMethod;
}
/**
* Set the value of defaultIdMethod.
* @param v Value to assign to defaultIdMethod.
*/
public function setDefaultIdMethod($v)
{
$this->defaultIdMethod = $v;
}
/**
* Get the value of defaultPHPNamingMethod which specifies the
* method for converting schema names for table and column to PHP names.
* @return string The default naming conversion used by this database.
*/
public function getDefaultPhpNamingMethod()
{
return $this->defaultPhpNamingMethod;
}
/**
* Set the value of defaultPHPNamingMethod.
* @param string $v The default naming conversion for this database to use.
*/
public function setDefaultPhpNamingMethod($v)
{
$this->defaultPhpNamingMethod = $v;
}
/**
* Get the value of defaultTranslateMethod which specifies the
* method for translate validator error messages.
* @return string The default translate method.
*/
public function getDefaultTranslateMethod()
{
return $this->defaultTranslateMethod;
}
/**
* Set the value of defaultTranslateMethod.
* @param string $v The default translate method to use.
*/
public function setDefaultTranslateMethod($v)
{
$this->defaultTranslateMethod = $v;
}
/**
* Get the value of heavyIndexing.
* @return boolean Value of heavyIndexing.
*/
public function isHeavyIndexing()
{
return $this->heavyIndexing;
}
/**
* Set the value of heavyIndexing.
* @param boolean $v Value to assign to heavyIndexing.
*/
public function setHeavyIndexing($v)
{
$this->heavyIndexing = (boolean) $v;
}
/**
* Return an array of all tables
*/
public function getTables()
{
return $this->tableList;
}
/**
* Return the table with the specified name.
* @param string $name The name of the table (e.g. 'my_table')
* @return Table a Table object or null if it doesn't exist
*/
public function getTable($name)
{
if (isset($this->tablesByName[$name])) {
return $this->tablesByName[$name];
}
return null; // just to be explicit
}
/**
* Return the table with the specified phpName.
* @param string $phpName the PHP Name of the table (e.g. 'MyTable')
* @return Table a Table object or null if it doesn't exist
*/
public function getTableByPhpName($phpName)
{
if (isset($this->tablesByPhpName[$phpName])) {
return $this->tablesByPhpName[$phpName];
}
return null; // just to be explicit
}
/**
* An utility method to add a new table from an xml attribute.
*/
public function addTable($data)
{
if ($data instanceof Table) {
$tbl = $data; // alias
$tbl->setDatabase($this);
if (isset($this->tablesByName[$tbl->getName()])) {
throw new EngineException("Duplicate table declared: " . $tbl->getName());
}
$this->tableList[] = $tbl;
$this->tablesByName[ $tbl->getName() ] = $tbl;
$this->tablesByPhpName[ $tbl->getPhpName() ] = $tbl;
if ($tbl->getPackage() === null) {
$tbl->setPackage($this->getPackage());
}
return $tbl;
} else {
$tbl = new Table();
$tbl->setDatabase($this);
$tbl->loadFromXML($data);
return $this->addTable($tbl); // call self w/ different param
}
}
/**
* Set the parent of the database
*/
public function setAppData(AppData $parent)
{
$this->dbParent = $parent;
}
/**
* Get the parent of the table
*/
public function getAppData()
{
return $this->dbParent;
}
/**
* Adds Domain object from <domain> tag.
* @param mixed XML attributes (array) or Domain object.
*/
public function addDomain($data) {
if ($data instanceof Domain) {
$domain = $data; // alias
$domain->setDatabase($this);
$this->domainMap[ $domain->getName() ] = $domain;
return $domain;
} else {
$domain = new Table();
$domain->setDatabase($this);
$domain->loadFromXML($data);
return $this->addDomain($domain); // call self w/ different param
}
}
/**
* Get already configured Domain object by name.
* @return Domain
*/
public function getDomain($domainName) {
if (!isset($this->domainMap[$domainName])) {
return null;
}
return $this->domainMap[$domainName];
}
public function doFinalInitialization()
{
$tables = $this->getTables();
for($i=0,$size=count($tables); $i < $size; $i++) {
$currTable = $tables[$i];
// check schema integrity
// if idMethod="autoincrement", make sure a column is
// specified as autoIncrement="true"
// FIXME: Handle idMethod="native" via DB adapter.
/*
--- REMOVING THIS BECAUSE IT'S ANNOYING
if ($currTable->getIdMethod() == IDMethod::NATIVE ) {
$columns = $currTable->getColumns();
$foundOne = false;
for ($j=0, $cLen=count($columns); $j < $cLen && !$foundOne; $j++) {
$foundOne = $columns[$j]->isAutoIncrement();
}
if (!$foundOne) {
$errorMessage = "Table '" . $currTable->getName()
. "' is set to use native id generation, but it does not "
. "have a column which declared as the one to "
. "auto increment (i.e. autoIncrement=\"true\")";
throw new BuildException($errorMessage);
}
}
*/
$currTable->doFinalInitialization();
// setup reverse fk relations
$fks = $currTable->getForeignKeys();
for ($j=0, $fksLen=count($fks); $j < $fksLen; $j++) {
$currFK = $fks[$j];
$foreignTable = $this->getTable($currFK->getForeignTableName());
if ($foreignTable === null) {
throw new BuildException("ERROR!! Attempt to set foreign"
. " key to nonexistent table, "
. $currFK->getForeignTableName() . "!");
}
$referrers = $foreignTable->getReferrers();
if ($referrers === null || ! in_array($currFK,$referrers) ) {
$foreignTable->addReferrer($currFK);
}
// local column references
$localColumnNames = $currFK->getLocalColumns();
for($k=0,$lcnLen=count($localColumnNames); $k < $lcnLen; $k++) {
$local = $currTable->getColumn($localColumnNames[$k]);
// give notice of a schema inconsistency.
// note we do not prevent the npe as there is nothing
// that we can do, if it is to occur.
if ($local === null) {
throw new BuildException("ERROR!! Attempt to define foreign"
. " key with nonexistent column, "
. $localColumnNames[$k] . ", in table, "
. $currTable->getName() . "!");
}
//check for foreign pk's
if ($local->isPrimaryKey()) {
$currTable->setContainsForeignPK(true);
}
} // for each local col name
// foreign column references
$foreignColumnNames = $currFK->getForeignColumns();
for($k=0,$fcnLen=count($localColumnNames); $k < $fcnLen; $k++) {
$foreign = $foreignTable->getColumn($foreignColumnNames[$k]);
// if the foreign column does not exist, we may have an
// external reference or a misspelling
if ($foreign === null) {
throw new BuildException("ERROR!! Attempt to set foreign"
. " key to nonexistent column, "
. $foreignColumnNames[$k] . ", in table, "
. $foreignTable->getName() . "!");
} else {
$foreign->addReferrer($currFK);
}
} // for each foreign col ref
}
}
}
/**
* Creats a string representation of this Database.
* The representation is given in xml format.
*/
public function toString()
{
$result = "<database name=\"" . $this->getName() . '"'
. " package=\"" . $this->getPackage() . '"'
. " defaultIdMethod=\"" . $this->getDefaultIdMethod()
. '"'
. " baseClass=\"" . $this->getBaseClass() . '"'
. " basePeer=\"" . $this->getBasePeer() . '"'
. ">\n";
for ($i=0, $size=count($this->tableList); $i < $size; $i++) {
$result .= $this->tableList[$i]->toString();
}
$result .= "</database>";
return $result;
}
}

View File

@ -0,0 +1,313 @@
<?php
/*
* $Id: Domain.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/database/model/XMLElement.php';
/**
* A Class for holding data about a column used in an Application.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Martin Poeschl <mpoeschl@marmot.at> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class Domain extends XMLElement {
private $name;
private $description;
private $size;
private $scale;
/** type as defined in schema.xml */
private $propelType;
private $sqlType;
private $defaultValue;
/** Database object -- in the event this Domain is specified in the XML. */
private $database;
/**
* Creates a new Domain object.
* If this domain needs a name, it must be specified manually.
*
* @param string $type Propel type.
* @param string $sqlType SQL type.
* @param string $size
* @param string $scale
*/
public function __construct($type = null, $sqlType = null, $size = null, $scale = null)
{
$this->propelType = $type;
$this->sqlType = ($sqlType !== null) ? $sqlType : $type;
$this->size = $size;
$this->scale = $scale;
}
public function copy(Domain $domain)
{
$this->defaultValue = $domain->getDefaultValue();
$this->description = $domain->getDescription();
$this->name = $domain->getName();
$this->scale = $domain->getScale();
$this->size = $domain->getSize();
$this->sqlType = $domain->getSqlType();
$this->propelType = $domain->getType();
}
/**
* Sets up the Domain object based on the attributes that were passed to loadFromXML().
* @see parent::loadFromXML()
*/
protected function setupObject()
{
$schemaType = strtoupper($this->getAttribute("type"));
$this->copy($this->getDatabase()->getPlatform()->getDomainForType($schemaType));
//Name
$this->name = $this->getAttribute("name");
//Default column value.
$this->defaultValue = $this->getAttribute("default"); // may need to adjust -- e.g. for boolean values
$this->size = $this->getAttribute("size");
$this->scale = $this->getAttribute("scale");
$this->description = $this->getAttribute("description");
}
/**
* Sets the owning database object (if this domain is being setup via XML).
*/
public function setDatabase(Database $database) {
$this->database = $database;
}
/**
* Gets the owning database object (if this domain was setup via XML).
*/
public function getDatabase() {
return $this->database;
}
/**
* @return Returns the description.
*/
public function getDescription()
{
return $this->description;
}
/**
* @param description The description to set.
*/
public function setDescription($description)
{
$this->description = $description;
}
/**
* @return Returns the name.
*/
public function getName()
{
return $this->name;
}
/**
* @param name The name to set.
*/
public function setName($name)
{
$this->name = $name;
}
/**
* @return Returns the scale.
*/
public function getScale()
{
return $this->scale;
}
/**
* @param scale The scale to set.
*/
public function setScale($scale)
{
$this->scale = $scale;
}
/**
* Replaces the size if the new value is not null.
*
* @param value The size to set.
*/
public function replaceScale($value)
{
if ($value !== null) {
$this->scale = $value;
}
}
/**
* @return Returns the size.
*/
public function getSize()
{
return $this->size;
}
/**
* @param size The size to set.
*/
public function setSize($size)
{
$this->size = $size;
}
/**
* Replaces the size if the new value is not null.
*
* @param value The size to set.
*/
public function replaceSize($value)
{
if ($value !== null) {
$this->size = $value;
}
}
/**
* @return string Returns the propelType.
*/
public function getType()
{
return $this->propelType;
}
/**
* @param string $propelType The PropelTypes type to set.
*/
public function setType($propelType)
{
$this->propelType = $propelType;
}
/**
* Replaces the default value if the new value is not null.
*
* @param value The defaultValue to set.
*/
public function replaceType($value)
{
if ($value !== null) {
$this->propelType = $value;
}
}
/**
* Gets the "raw" default value, suitable for use in SQL.
* @return string Returns the defaultValue.
*/
public function getDefaultValue()
{
if ($this->defaultValue !== null) {
return $this->defaultValue;
}
}
/**
* Gets the default value, type-casted for use in PHP OM.
* @return mixed
* @see getDefaultValue()
*/
public function getPhpDefaultValue()
{
if ($this->defaultValue === null) {
return null;
} elseif ($this->propelType === PropelTypes::BOOLEAN) {
// convert "true" => TRUE
return $this->booleanValue($this->defaultValue);
} elseif ($this->propelType === PropelTypes::DATE || $this->propelType === PropelTypes::TIME || $this->propelType === PropelTypes::TIMESTAMP) {
// DATE/TIME vals need to be converted to integer timestamp
$ts = strtotime($this->defaultValue);
if ($ts === -1 || $ts === false) { // in PHP 5.1 return value changes to FALSE
throw new EngineException("Unable to parse default value as date/time value: " . var_export($this->defaultValue, true));
}
return $ts;
} else {
return $this->defaultValue;
}
}
/**
* @param defaultValue The defaultValue to set.
*/
public function setDefaultValue($defaultValue)
{
$this->defaultValue = $defaultValue;
}
/**
* Replaces the default value if the new value is not null.
*
* @param string $value The defaultValue to set.
*/
public function replaceDefaultValue($value)
{
if ($value !== null) {
$this->defaultValue = $value;
}
}
/**
* @return Returns the sqlType.
*/
public function getSqlType()
{
return $this->sqlType;
}
/**
* @param string $sqlType The sqlType to set.
*/
public function setSqlType($sqlType)
{
$this->sqlType = $sqlType;
}
/**
* Return the size and scale in brackets for use in an sql schema.
*
* @return size and scale or an empty String if there are no values
* available.
*/
public function printSize()
{
if ($this->size !== null && $this->scale !== null) {
return '(' . $this->size . ',' . $this->scale . ')';
} elseif ($this->size !== null) {
return '(' . $this->size . ')';
} else {
return "";
}
}
}

View File

@ -0,0 +1,278 @@
<?php
/*
* $Id: ForeignKey.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/database/model/XMLElement.php';
/**
* A Class for information about foreign keys of a table.
*
* @author Hans Lellelid <hans@xmpl.org>
* @author Fedor <fedor.karpelevitch@home.com>
* @author Daniel Rall <dlr@finemaltcoding.com>
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class ForeignKey extends XMLElement {
private $foreignTableName;
private $name;
private $onUpdate;
private $onDelete;
private $parentTable;
private $localColumns = array();
private $foreignColumns = array();
// the uppercase equivalent of the onDelete/onUpdate values in the dtd
const NONE = ""; // No "ON [ DELETE | UPDATE]" behaviour specified.
const NOACTION = "NO ACTION";
const CASCADE = "CASCADE";
const RESTRICT = "RESTRICT";
const SETDEFAULT = "SET DEFAULT";
const SETNULL = "SET NULL";
/**
* Sets up the ForeignKey object based on the attributes that were passed to loadFromXML().
* @see parent::loadFromXML()
*/
protected function setupObject()
{
$this->foreignTableName = $this->getAttribute("foreignTable");
$this->name = $this->getAttribute("name");
$this->onUpdate = $this->normalizeFKey($this->getAttribute("onUpdate"));
$this->onDelete = $this->normalizeFKey($this->getAttribute("onDelete"));
}
/**
* normalizes the input of onDelete, onUpdate attributes
*/
private function normalizeFKey($attrib)
{
if ($attrib === null || strtoupper($attrib) == "NONE") {
$attrib = self::NONE;
}
$attrib = strtoupper($attrib);
if ($attrib == "SETNULL") {
$attrib = self::SETNULL;
}
return $attrib;
}
/**
* returns whether or not the onUpdate attribute is set
*/
public function hasOnUpdate()
{
return ($this->onUpdate !== self::NONE);
}
/**
* returns whether or not the onDelete attribute is set
*/
public function hasOnDelete()
{
return ($this->onDelete !== self::NONE);
}
/**
* returns the onUpdate attribute
*/
public function getOnUpdate()
{
return $this->onUpdate;
}
/**
* returns the onDelete attribute
*/
public function getOnDelete()
{
return $this->onDelete;
}
/**
* sets the onDelete attribute
*/
public function setOnDelete($value)
{
$this->onDelete = $this->normalizeFKey($value);
}
/**
* sets the onUpdate attribute
*/
public function setOnUpdate($value)
{
$this->onUpdate = $this->normalizeFKey($value);
}
/**
* Returns the name attribute.
*/
public function getName()
{
return $this->name;
}
/**
* Sets the name attribute.
*/
public function setName($name)
{
$this->name = $name;
}
/**
* Get the foreignTableName of the FK
*/
public function getForeignTableName()
{
return $this->foreignTableName;
}
/**
* Set the foreignTableName of the FK
*/
public function setForeignTableName($tableName)
{
$this->foreignTableName = $tableName;
}
/**
* Set the parent Table of the foreign key
*/
public function setTable(Table $parent)
{
$this->parentTable = $parent;
}
/**
* Get the parent Table of the foreign key
*/
public function getTable()
{
return $this->parentTable;
}
/**
* Returns the Name of the table the foreign key is in
*/
public function getTableName()
{
return $this->parentTable->getName();
}
/**
* adds a new reference entry to the foreign key
*/
public function addReference($p1, $p2 = null)
{
if (is_array($p1)) {
$this->addReference(@$p1["local"], @$p1["foreign"]);
} else {
$this->localColumns[] = $p1;
$this->foreignColumns[] = $p2;
}
}
/**
* Return a comma delimited string of local column names
* @deprecated because Column::makeList() is deprecated; use the array-returning getLocalColumns() and DDLBuilder->getColumnList() instead instead.
*/
public function getLocalColumnNames()
{
return Column::makeList($this->getLocalColumns(), $this->getTable()->getDatabase()->getPlatform());
}
/**
* Return a comma delimited string of foreign column names
* @deprecated because Column::makeList() is deprecated; use the array-returning getForeignColumns() and DDLBuilder->getColumnList() instead instead.
*/
public function getForeignColumnNames()
{
return Column::makeList($this->getForeignColumns(), $this->getTable()->getDatabase()->getPlatform());
}
/**
* Return an array of local column names.
* @return array string[]
*/
public function getLocalColumns()
{
return $this->localColumns;
}
/**
* Utility method to get local column to foreign column
* mapping for this foreign key.
*/
public function getLocalForeignMapping()
{
$h = array();
for ($i=0, $size=count($this->localColumns); $i < $size; $i++) {
$h[$this->localColumns[$i]] = $this->foreignColumns[$i];
}
return $h;
}
/**
* Return an array of foreign column names.
* @return array string[]
*/
public function getForeignColumns()
{
return $this->foreignColumns;
}
/**
* Utility method to get local column to foreign column
* mapping for this foreign key.
*/
public function getForeignLocalMapping()
{
$h = array();
for ($i=0, $size=count($this->localColumns); $i < $size; $i++) {
$h[ $this->foreignColumns[$i] ] = $this->localColumns[$i];
}
return $h;
}
/**
* String representation of the foreign key. This is an xml representation.
*/
public function toString()
{
$result = " <foreign-key foreignTable=\""
. $this->getForeignTableName()
. "\" name=\""
. $this->getName()
. "\">\n";
for ($i=0, $size=count($this->localColumns); $i < $size; $i++) {
$result .= " <reference local=\""
. $this->localColumns[$i]
. "\" foreign=\""
. $this->foreignColumns[$i]
. "\"/>\n";
}
$result .= " </foreign-key>\n";
return $result;
}
}

View File

@ -0,0 +1,46 @@
<?php
/*
* $Id: IDMethod.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
/**
* Interface for various ID retrieval method types
* (i.e. auto-increment, sequence, ID broker, etc.).
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Daniel Rall <dlr@collab.net> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
interface IDMethod {
/**
* Key generation via database-specific ID method
* (i.e. auto-increment for MySQL, sequence for Oracle, etc.).
*/
const NATIVE = "native";
/**
* No RDBMS key generation (keys may be generated by the
* application).
*/
const NO_ID_METHOD = "none";
}

View File

@ -0,0 +1,125 @@
<?php
/*
* $Id: IdMethodParameter.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/database/model/XMLElement.php';
/**
* Information related to an ID method.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author John McNally <jmcnally@collab.net> (Torque)
* @author Daniel Rall <dlr@collab.net> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class IdMethodParameter extends XMLElement {
private $name;
private $value;
private $parentTable;
/**
* Sets up the IdMethodParameter object based on the attributes that were passed to loadFromXML().
* @see parent::loadFromXML()
*/
protected function setupObject()
{
$this->name = $this->getAttribute("name");
$this->value = $this->getAttribute("value");
}
/**
* Get the parameter name
*/
public function getName()
{
return $this->name;
}
/**
* Set the parameter name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* Get the parameter value
*/
public function getValue()
{
return $this->value;
}
/**
* Set the parameter value
*/
public function setValue($value)
{
$this->value = $value;
}
/**
* Set the parent Table of the id method
*/
public function setTable(Table $parent)
{
$this->parentTable = $parent;
}
/**
* Get the parent Table of the id method
*/
public function getTable()
{
return $this->parentTable;
}
/**
* Returns the Name of the table the id method is in
*/
public function getTableName()
{
return $this->parentTable->getName();
}
/**
* XML representation of the foreign key.
*/
public function toString()
{
$result = " <id-method-parameter";
if ($this->getName() !== null) {
$result .= " name=\""
. $this->getName()
. '"';
}
$result .= " value=\""
. $this->getValue()
. "\">\n";
return $result;
}
}

View File

@ -0,0 +1,276 @@
<?php
/*
* $Id: Index.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/database/model/XMLElement.php';
include_once 'propel/engine/EngineException.php';
/**
* Information about indices of a table.
*
* @author Jason van Zyl <vanzyl@apache.org>
* @author Daniel Rall <dlr@finemaltcoding.com>
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class Index extends XMLElement {
/** enables debug output */
const DEBUG = false;
private $indexName;
private $parentTable;
/** @var array string[] */
private $indexColumns;
/** @var array */
private $indexColumnSizes = array();
/**
* Creates a new instance with default characteristics (no name or
* parent table, small column list size allocation, non-unique).
*
* @param Table $table
* @param array $indexColumns
*/
public function __construct(Table $table, $indexColumns = array())
{
$this->indexColumns = $indexColumns;
$this->setTable($table);
if (!empty($indexColumns)) {
$this->createName();
if (self::DEBUG) {
print("Created Index named " . $this->getName()
. " with " . count($indexColumns) . " columns\n");
}
}
}
private function createName()
{
$table = $this->getTable();
$inputs = array();
$inputs[] = $table->getDatabase();
$inputs[] = $table->getName();
if ($this->isUnique()) {
$inputs[] = "U";
} else {
$inputs[] = "I";
}
// ASSUMPTION: This Index not yet added to the list.
if ($this->isUnique()) {
$inputs[] = count($table->getUnices()) + 1;
} else {
$inputs[] = count($table->getIndices()) + 1;
}
$this->indexName = NameFactory::generateName(
NameFactory::CONSTRAINT_GENERATOR, $inputs);
}
/**
* Sets up the Index object based on the attributes that were passed to loadFromXML().
* @see parent::loadFromXML()
*/
protected function setupObject()
{
$this->indexName = $this->getAttribute("name");
}
/**
* @see #isUnique()
* @deprecated Use isUnique() instead.
*/
public function getIsUnique()
{
return $this->isUnique();
}
/**
* Returns the uniqueness of this index.
*/
public function isUnique()
{
return false;
}
/**
* @see #getName()
* @deprecated Use getName() instead.
*/
public function getIndexName()
{
return $this->getName();
}
/**
* Gets the name of this index.
*/
public function getName()
{
if ($this->indexName === null) {
try {
// generate an index name if we don't have a supplied one
$this->createName();
} catch (EngineException $e) {
// still no name
}
}
return $this->indexName;
}
/**
* @see #setName(String name)
* @deprecated Use setName(String name) instead.
*/
public function setIndexName($name)
{
$this->setName($name);
}
/**
* Set the name of this index.
*/
public function setName($name)
{
$this->indexName = $name;
}
/**
* Set the parent Table of the index
*/
public function setTable(Table $parent)
{
$this->parentTable = $parent;
}
/**
* Get the parent Table of the index
*/
public function getTable()
{
return $this->parentTable;
}
/**
* Returns the Name of the table the index is in
*/
public function getTableName()
{
return $this->parentTable->getName();
}
/**
* Adds a new column to an index.
* @param array $attrib The attribute array from XML parser.
*/
public function addColumn($attrib)
{
$name = $attrib["name"];
$this->indexColumns[] = $name;
if (isset($attrib["size"])) {
$this->indexColumnSizes[$name] = $attrib["size"];
}
}
/**
* Whether there is a size for the specified column.
* @param string $name
* @return boolean
*/
public function hasColumnSize($name)
{
return isset($this->indexColumnSizes[$name]);
}
/**
* Returns the size for the specified column, if given.
* @param string $name
* @return numeric The size or NULL
*/
public function getColumnSize($name)
{
if (isset($this->indexColumnSizes[$name])) {
return $this->indexColumnSizes[$name];
}
return null; // just to be explicit
}
/**
* @see #getColumnList()
* @deprecated Use getColumnList() instead (which is not deprecated too!)
*/
public function getIndexColumnList()
{
return $this->getColumnList();
}
/**
* Return a comma delimited string of the columns which compose this index.
* @deprecated because Column::makeList() is deprecated; use the array-returning getColumns() and DDLBuilder->getColumnList() instead instead.
*/
public function getColumnList()
{
return Column::makeList($this->getColumns(), $this->getTable()->getDatabase()->getPlatform());
}
/**
* @see #getColumns()
* @deprecated Use getColumns() instead.
*/
public function getIndexColumns()
{
return $this->getColumns();
}
/**
* Return the list of local columns. You should not edit this list.
* @return array string[]
*/
public function getColumns()
{
return $this->indexColumns;
}
/**
* String representation of the index. This is an xml representation.
*/
public function toString()
{
$result = " <index name=\""
. $this->getName()
.'"';
$result .= ">\n";
for ($i=0, $size=count($this->indexColumns); $i < $size; $i++) {
$result .= " <index-column name=\""
. $this->indexColumns[$i]
. "\"/>\n";
}
$result .= " </index>\n";
return $result;
}
}

View File

@ -0,0 +1,164 @@
<?php
/*
* $Id: Inheritance.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/database/model/XMLElement.php';
/**
* A Class for information regarding possible objects representing a table
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author John McNally <jmcnally@collab.net> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class Inheritance extends XMLElement {
private $key;
private $className;
private $pkg;
private $ancestor;
private $parent;
/**
* Sets up the Inheritance object based on the attributes that were passed to loadFromXML().
* @see parent::loadFromXML()
*/
protected function setupObject()
{
$this->key = $this->getAttribute("key");
$this->className = $this->getAttribute("class");
$this->pkg = $this->getAttribute("package");
$this->ancestor = $this->getAttribute("extends");
}
/**
* Get the value of key.
* @return value of key.
*/
public function getKey()
{
return $this->key;
}
/**
* Set the value of key.
* @param v Value to assign to key.
*/
public function setKey($v)
{
$this->key = $v;
}
/**
* Get the value of parent.
* @return value of parent.
*/
public function getColumn()
{
return $this->parent;
}
/**
* Set the value of parent.
* @param v Value to assign to parent.
*/
public function setColumn(Column $v)
{
$this->parent = $v;
}
/**
* Get the value of className.
* @return value of className.
*/
public function getClassName()
{
return $this->className;
}
/**
* Set the value of className.
* @param v Value to assign to className.
*/
public function setClassName($v)
{
$this->className = $v;
}
/**
* Get the value of package.
* @return value of package.
*/
public function getPackage()
{
return $this->pkg;
}
/**
* Set the value of package.
* @param v Value to assign to package.
*/
public function setPackage($v)
{
$this->pkg = $v;
}
/**
* Get the value of ancestor.
* @return value of ancestor.
*/
public function getAncestor()
{
return $this->ancestor;
}
/**
* Set the value of ancestor.
* @param v Value to assign to ancestor.
*/
public function setAncestor($v)
{
$this->ancestor = $v;
}
/**
* String representation of the foreign key. This is an xml representation.
*/
public function toString()
{
$result = " <inheritance key=\""
. $this->key
. "\" class=\""
. $this->className
. '"';
if ($this->ancestor !== null) {
$result .= " extends=\""
. $this->ancestor
. '"';
}
$result .= "/>";
return $result;
}
}

View File

@ -0,0 +1,116 @@
<?php
/*
* $Id: NameFactory.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
include_once 'propel/engine/EngineException.php';
include_once 'propel/engine/database/model/NameGenerator.php';
/**
* A name generation factory.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Daniel Rall <dlr@finemaltcoding.com> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class NameFactory {
/**
* The class name of the PHP name generator.
*/
const PHP_GENERATOR = 'PhpNameGenerator';
/**
* The fully qualified class name of the constraint name generator.
*/
const CONSTRAINT_GENERATOR = 'ConstraintNameGenerator';
/**
* The single instance of this class.
*/
private static $instance;
/**
* The cache of <code>NameGenerator</code> algorithms in use for
* name generation, keyed by fully qualified class name.
*/
private $algorithms;
/**
* Creates a new instance with storage for algorithm implementations.
*/
protected function __construct()
{
$this->algorithms = array();
}
private static function instance()
{
if (self::$instance === null) {
self::$instance = new NameFactory();
}
return self::$instance;
}
/**
* Factory method which retrieves an instance of the named generator.
*
* @param name The fully qualified class name of the name
* generation algorithm to retrieve.
*/
protected function getAlgorithm($name)
{
$algorithm = isset($this->algorithms[$name]) ? $this->algorithms[$name] : null;
if ($algorithm === null) {
try {
include_once 'propel/engine/database/model/' . $name . '.php';
if (!class_exists($name)) {
throw new Exception("Unable to instantiate class " . $name
. ": Make sure it's in your include_path");
}
$algorithm = new $name();
} catch (BuildException $e) {
print $e->getMessage() . "\n";
print $e->getTraceAsString();
}
$this->algorithms[$name] = $algorithm;
}
return $algorithm;
}
/**
* Given a list of <code>String</code> objects, implements an
* algorithm which produces a name.
*
* @param algorithmName The fully qualified class name of the
* {@link NameGenerator}
* implementation to use to generate names.
* @param array $inputs Inputs used to generate a name.
* @return The generated name.
* @throws EngineException
*/
public static function generateName($algorithmName, $inputs)
{
$algorithm = self::instance()->getAlgorithm($algorithmName);
return $algorithm->generateName($inputs);
}
}

View File

@ -0,0 +1,72 @@
<?php
/*
* $Id: NameGenerator.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
/**
* The generic interface to a name generation algorithm.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Daniel Rall <dlr@finemaltcoding.com> (Torque)
* @author Byron Foster <byron_foster@yahoo.com> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
interface NameGenerator {
/**
* The character used by most implementations as the separator
* between name elements.
*/
const STD_SEPARATOR_CHAR = '_';
/**
* Traditional method for converting schema table and column names
* to PHP names. The <code>CONV_METHOD_XXX</code> constants
* define how names for columns and tables in the database schema
* will be converted to PHP source names.
*
* @see PhpNameGenerator::underscoreMethod()
*/
const CONV_METHOD_UNDERSCORE = "underscore";
/**
* Similar to {@link #CONV_METHOD_UNDERSCORE} except nothing is
* converted to lowercase.
*
* @see PhpNameGenerator::phpnameMethod()
*/
const CONV_METHOD_PHPNAME = "phpname";
/**
* Specifies no modification when converting from a schema column
* or table name to a PHP name.
*/
const CONV_METHOD_NOCHANGE = "nochange";
/**
* Given a list of <code>String</code> objects, implements an
* algorithm which produces a name.
*
* @param inputs Inputs used to generate a name.
* @return The generated name.
* @throws EngineException
*/
public function generateName($inputs);
}

View File

@ -0,0 +1,131 @@
<?php
/*
* $Id: PhpNameGenerator.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
include_once 'propel/engine/database/model/NameGenerator.php';
/**
* A <code>NameGenerator</code> implementation for PHP-esque names.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Daniel Rall <dlr@finemaltcoding.com> (Torque)
* @author Byron Foster <byron_foster@yahoo.com> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class PhpNameGenerator implements NameGenerator {
/**
* <code>inputs</code> should consist of two elements, the
* original name of the database element and the method for
* generating the name. There are currently three methods:
* <code>CONV_METHOD_NOCHANGE</code> - xml names are converted
* directly to php names without modification.
* <code>CONV_METHOD_UNDERSCORE</code> will capitalize the first
* letter, remove underscores, and capitalize each letter before
* an underscore. All other letters are lowercased. "phpname"
* works the same as the <code>CONV_METHOD_PHPNAME</code> method
* but will not lowercase any characters.
*
* @param inputs list expected to contain two parameters, element
* 0 contains name to convert, element 1 contains method for conversion.
* @return The generated name.
* @see NameGenerator
*/
public function generateName($inputs)
{
$schemaName = $inputs[0];
$method = $inputs[1];
$phpName = null;
if ($method == self::CONV_METHOD_UNDERSCORE) {
$phpName = $this->underscoreMethod($schemaName);
} elseif ($method == self::CONV_METHOD_PHPNAME) {
$phpName = $this->phpnameMethod($schemaName);
} else if ($method == self::CONV_METHOD_NOCHANGE) {
$phpName = $this->nochangeMethod($schemaName);
} else {
// if for some reason nothing is defined then we default
// to the traditional method.
$phpName = $this->underscoreMethod($schemaName);
}
return $phpName;
}
/**
* Converts a database schema name to php object name. Removes
* <code>STD_SEPARATOR_CHAR</code>, capitilizes first letter of
* name and each letter after the <code>STD_SEPERATOR</code>,
* converts the rest of the letters to lowercase.
*
* my_CLASS_name -> MyClassName
*
* @param string $schemaName name to be converted.
* @return string Converted name.
* @see NameGenerator
* @see #underscoreMethod()
*/
protected function underscoreMethod($schemaName)
{
$name = "";
$tok = strtok($schemaName, self::STD_SEPARATOR_CHAR);
while($tok) {
$name .= ucfirst(strtolower($tok));
$tok = strtok(self::STD_SEPARATOR_CHAR);
}
return $name;
}
/**
* Converts a database schema name to php object name. Operates
* same as underscoreMethod but does not convert anything to
* lowercase.
*
* my_CLASS_name -> MyCLASSName
*
* @param string $schemaName name to be converted.
* @return string Converted name.
* @see NameGenerator
* @see #underscoreMethod(String)
*/
protected function phpnameMethod($schemaName)
{
$name = "";
$tok = strtok($schemaName, self::STD_SEPARATOR_CHAR);
while($tok) {
$name .= ucfirst($tok);
$tok = strtok(self::STD_SEPARATOR_CHAR);
}
return $name;
}
/**
* Converts a database schema name to PHP object name. In this
* case no conversion is made.
*
* @param string $name name to be converted.
* @return string The <code>name</code> parameter, unchanged.
*/
protected function nochangeMethod($name)
{
return $name;
}
}

View File

@ -0,0 +1,290 @@
<?php
/*
* $Id: PropelTypes.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'creole/CreoleTypes.php';
/**
* A class that maps PropelTypes to CreoleTypes and to native PHP types.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Jason van Zyl <jvanzyl@apache.org> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class PropelTypes {
const CHAR = "CHAR";
const VARCHAR = "VARCHAR";
const LONGVARCHAR = "LONGVARCHAR";
const CLOB = "CLOB";
const NUMERIC = "NUMERIC";
const DECIMAL = "DECIMAL";
const TINYINT = "TINYINT";
const SMALLINT = "SMALLINT";
const INTEGER = "INTEGER";
const BIGINT = "BIGINT";
const REAL = "REAL";
const FLOAT = "FLOAT";
const DOUBLE = "DOUBLE";
const BINARY = "BINARY";
const VARBINARY = "VARBINARY";
const LONGVARBINARY = "LONGVARBINARY";
const BLOB = "BLOB";
const DATE = "DATE";
const TIME = "TIME";
const TIMESTAMP = "TIMESTAMP";
const BU_DATE = "BU_DATE";
const BU_TIMESTAMP = "BU_TIMESTAMP";
const BOOLEAN = "BOOLEAN";
private static $TEXT_TYPES = null;
private static $LOB_TYPES = null;
const CHAR_NATIVE_TYPE = "string";
const VARCHAR_NATIVE_TYPE = "string";
const LONGVARCHAR_NATIVE_TYPE = "string";
const CLOB_NATIVE_TYPE = "string"; // Clob
const NUMERIC_NATIVE_TYPE = "double";
const DECIMAL_NATIVE_TYPE = "double";
const BOOLEAN_NATIVE_TYPE = "boolean";
const TINYINT_NATIVE_TYPE = "int";
const SMALLINT_NATIVE_TYPE = "int";
const INTEGER_NATIVE_TYPE = "int";
const BIGINT_NATIVE_TYPE = "string";
const REAL_NATIVE_TYPE = "double";
const FLOAT_NATIVE_TYPE = "double";
const DOUBLE_NATIVE_TYPE = "double";
const BINARY_NATIVE_TYPE = "string";
const VARBINARY_NATIVE_TYPE = "string";
const LONGVARBINARY_NATIVE_TYPE = "string";
const BLOB_NATIVE_TYPE = "string";
const BU_DATE_NATIVE_TYPE = "string";
const DATE_NATIVE_TYPE = "int";
const TIME_NATIVE_TYPE = "int";
const TIMESTAMP_NATIVE_TYPE = "int";
const BU_TIMESTAMP_NATIVE_TYPE = "string";
private static $propelToPHPNativeMap = null;
private static $propelTypeToCreoleTypeMap = null;
private static $creoleToPropelTypeMap = null;
private static $isInitialized = false;
/**
* Initializes the SQL to PHP map so that it
* can be used by client code.
*/
public static function initialize()
{
if (self::$isInitialized === false) {
self::$TEXT_TYPES = array (
self::CHAR, self::VARCHAR, self::LONGVARCHAR, self::CLOB, self::DATE, self::TIME, self::TIMESTAMP, self::BU_DATE, self::BU_TIMESTAMP
);
self::$LOB_TYPES = array (
self::VARBINARY, self::LONGVARBINARY, self::CLOB, self::BLOB
);
/*
* Create Creole -> native PHP type mappings.
*/
self::$propelToPHPNativeMap = array();
self::$propelToPHPNativeMap[self::CHAR] = self::CHAR_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::VARCHAR] = self::VARCHAR_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::LONGVARCHAR] = self::LONGVARCHAR_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::CLOB] = self::CLOB_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::NUMERIC] = self::NUMERIC_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::DECIMAL] = self::DECIMAL_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::TINYINT] = self::TINYINT_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::SMALLINT] = self::SMALLINT_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::INTEGER] = self::INTEGER_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::BIGINT] = self::BIGINT_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::REAL] = self::REAL_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::FLOAT] = self::FLOAT_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::DOUBLE] = self::DOUBLE_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::BINARY] = self::BINARY_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::VARBINARY] = self::VARBINARY_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::LONGVARBINARY] = self::LONGVARBINARY_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::BLOB] = self::BLOB_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::DATE] = self::DATE_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::BU_DATE] = self::BU_DATE_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::TIME] = self::TIME_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::TIMESTAMP] = self::TIMESTAMP_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::BU_TIMESTAMP] = self::BU_TIMESTAMP_NATIVE_TYPE;
self::$propelToPHPNativeMap[self::BOOLEAN] = self::BOOLEAN_NATIVE_TYPE;
/*
* Create Propel -> Creole _name_ mappings (not CreoleType:: mappings).
* (this is now pretty useless since we've designed them to be the same!)
*/
self::$propelTypeToCreoleTypeMap = array();
self::$propelTypeToCreoleTypeMap[self::CHAR] = self::CHAR;
self::$propelTypeToCreoleTypeMap[self::VARCHAR] = self::VARCHAR;
self::$propelTypeToCreoleTypeMap[self::LONGVARCHAR] = self::LONGVARCHAR;
self::$propelTypeToCreoleTypeMap[self::CLOB] = self::CLOB;
self::$propelTypeToCreoleTypeMap[self::NUMERIC] = self::NUMERIC;
self::$propelTypeToCreoleTypeMap[self::DECIMAL] = self::DECIMAL;
self::$propelTypeToCreoleTypeMap[self::TINYINT] = self::TINYINT;
self::$propelTypeToCreoleTypeMap[self::SMALLINT] = self::SMALLINT;
self::$propelTypeToCreoleTypeMap[self::INTEGER] = self::INTEGER;
self::$propelTypeToCreoleTypeMap[self::BIGINT] = self::BIGINT;
self::$propelTypeToCreoleTypeMap[self::REAL] = self::REAL;
self::$propelTypeToCreoleTypeMap[self::FLOAT] = self::FLOAT;
self::$propelTypeToCreoleTypeMap[self::DOUBLE] = self::DOUBLE;
self::$propelTypeToCreoleTypeMap[self::BINARY] = self::BINARY;
self::$propelTypeToCreoleTypeMap[self::VARBINARY] = self::VARBINARY;
self::$propelTypeToCreoleTypeMap[self::LONGVARBINARY] = self::LONGVARBINARY;
self::$propelTypeToCreoleTypeMap[self::BLOB] = self::BLOB;
self::$propelTypeToCreoleTypeMap[self::DATE] = self::DATE;
self::$propelTypeToCreoleTypeMap[self::TIME] = self::TIME;
self::$propelTypeToCreoleTypeMap[self::TIMESTAMP] = self::TIMESTAMP;
self::$propelTypeToCreoleTypeMap[self::BOOLEAN] = self::BOOLEAN;
// These are pre-epoch dates, which we need to map to String type
// since they cannot be properly handled using strtotime() -- or even numeric
// timestamps on Windows.
self::$propelTypeToCreoleTypeMap[self::BU_DATE] = self::VARCHAR;
self::$propelTypeToCreoleTypeMap[self::BU_TIMESTAMP] = self::VARCHAR;
/*
* Create Creole type code to Propel type map.
*/
self::$creoleToPropelTypeMap = array();
self::$creoleToPropelTypeMap[CreoleTypes::CHAR] = self::CHAR;
self::$creoleToPropelTypeMap[CreoleTypes::VARCHAR] = self::VARCHAR;
self::$creoleToPropelTypeMap[CreoleTypes::LONGVARCHAR] = self::LONGVARCHAR;
self::$creoleToPropelTypeMap[CreoleTypes::CLOB] = self::CLOB;
self::$creoleToPropelTypeMap[CreoleTypes::NUMERIC] = self::NUMERIC;
self::$creoleToPropelTypeMap[CreoleTypes::DECIMAL] = self::DECIMAL;
self::$creoleToPropelTypeMap[CreoleTypes::TINYINT] = self::TINYINT;
self::$creoleToPropelTypeMap[CreoleTypes::SMALLINT] = self::SMALLINT;
self::$creoleToPropelTypeMap[CreoleTypes::INTEGER] = self::INTEGER;
self::$creoleToPropelTypeMap[CreoleTypes::BIGINT] = self::BIGINT;
self::$creoleToPropelTypeMap[CreoleTypes::REAL] = self::REAL;
self::$creoleToPropelTypeMap[CreoleTypes::FLOAT] = self::FLOAT;
self::$creoleToPropelTypeMap[CreoleTypes::DOUBLE] = self::DOUBLE;
self::$creoleToPropelTypeMap[CreoleTypes::BINARY] = self::BINARY;
self::$creoleToPropelTypeMap[CreoleTypes::VARBINARY] = self::VARBINARY;
self::$creoleToPropelTypeMap[CreoleTypes::LONGVARBINARY] = self::LONGVARBINARY;
self::$creoleToPropelTypeMap[CreoleTypes::BLOB] = self::BLOB;
self::$creoleToPropelTypeMap[CreoleTypes::DATE] = self::DATE;
self::$creoleToPropelTypeMap[CreoleTypes::TIME] = self::TIME;
self::$creoleToPropelTypeMap[CreoleTypes::TIMESTAMP] = self::TIMESTAMP;
self::$creoleToPropelTypeMap[CreoleTypes::BOOLEAN] = self::BOOLEAN;
self::$creoleToPropelTypeMap[CreoleTypes::YEAR] = self::INTEGER;
self::$isInitialized = true;
}
}
/**
* Report whether this object has been initialized.
*
* @return true if this object has been initialized
*/
public static function isInitialized()
{
return self::$isInitialized;
}
/**
* Return native PHP type which corresponds to the
* Creole type provided. Use in the base object class generation.
*
* @param $propelType The Propel type name.
* @return string Name of the native PHP type
*/
public static function getPhpNative($propelType)
{
return self::$propelToPHPNativeMap[$propelType];
}
/**
* Returns the correct Creole type _name_ for propel added types
*
* @param $type the propel added type.
* @return string Name of the the correct Creole type (e.g. "VARCHAR").
*/
public static function getCreoleType($type)
{
return self::$propelTypeToCreoleTypeMap[$type];
}
/**
* Returns Propel type constant corresponding to Creole type code.
* Used but Propel Creole task.
*
* @param int $sqlType The Creole SQL type constant.
* @return string The Propel type to use or NULL if none found.
*/
public static function getPropelType($sqlType)
{
if (isset(self::$creoleToPropelTypeMap[$sqlType])) {
return self::$creoleToPropelTypeMap[$sqlType];
}
}
/**
* Get array of Propel types.
*
* @return array string[]
*/
public static function getPropelTypes()
{
return array_keys(self::$propelTypeToCreoleTypeMap);
}
/**
* Returns true if values for the type need to be quoted.
*
* @param string $type The Propel type to check.
* @return true if values for the type need to be quoted.
*/
public static function isTextType($type)
{
// Make sure the we are initialized.
if (self::$isInitialized === false) {
self::initialize();
}
return in_array($type, self::$TEXT_TYPES);
}
/**
* Returns true if type is a LOB type (i.e. would be handled by Blob/Clob class).
* @param string $type Propel type to check.
* @return boolean
*/
public static function isLobType($type)
{
return in_array($type, self::$LOB_TYPES);
}
}
// static
PropelTypes::initialize();

View File

@ -0,0 +1,203 @@
<?php
/*
* $Id: Rule.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/database/model/XMLElement.php';
/**
* Data about a validation rule used in an application.
*
* @author Michael Aichler <aichler@mediacluster.de> (Propel)
* @author John McNally <jmcnally@collab.net> (Intake)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class Rule extends XMLElement {
private $name;
private $value;
private $message;
private $validator;
private $classname;
/**
* Sets up the Rule object based on the attributes that were passed to loadFromXML().
* @see parent::loadFromXML()
*/
protected function setupObject()
{
$this->name = $this->getAttribute("name");
$this->value = $this->getAttribute("value");
$this->classname = $this->getAttribute("class");
/*
* Set some default values if they are not specified.
* This is escpecially useful for maxLength; the size
* is already known by the column and this way it is
* not necessary to manage the same size two times.
*
* Currently there is only one such supported default:
* - maxLength value = column max length
* (this default cannot be easily set at runtime w/o changing
* design of class system in undesired ways)
*/
if ($this->value === null) {
switch($this->name) {
case 'maxLength':
$this->value = $this->validator->getColumn()->getSize();
break;
}
}
$this->message = $this->getAttribute("message");
}
/**
* Sets the owning validator for this rule.
* @param Validator $validator
* @see Validator::addRule()
*/
public function setValidator(Validator $validator)
{
$this->validator = $validator;
}
/**
* Gets the owning validator for this rule.
* @return Validator
*/
public function getValidator()
{
return $this->validator;
}
/**
* Sets the dot-path name of class to use for rule.
* If no class is specified in XML, then a classname will
* be built based on the 'name' attrib.
* @param string $classname dot-path classname (e.g. myapp.propel.MyValidator)
*/
public function setClass($classname)
{
$this->classname = $classname;
}
/**
* Gets the dot-path name of class to use for rule.
* If no class was specified, this method will build a default classname
* based on the 'name' attribute. E.g. 'maxLength' -> 'propel.validator.MaxLengthValidator'
* @return string dot-path classname (e.g. myapp.propel.MyValidator)
*/
public function getClass()
{
if ($this->classname === null && $this->name !== null) {
return "propel.validator." . ucfirst($this->name) . "Validator";
}
return $this->classname;
}
/**
* Sets the name of the validator for this rule.
* This name is used to build the classname if none was specified.
* @param string $name Validator name for this rule (e.g. "maxLength", "required").
* @see getClass()
*/
public function setName($name)
{
$this->name = $name;
}
/**
* Gets the name of the validator for this rule.
* @return string Validator name for this rule (e.g. "maxLength", "required").
*/
public function getName()
{
return $this->name;
}
/**
* Sets the value parameter for this validator rule.
* Note: not all validators need a value parameter (e.g. 'required' validator
* does not).
* @param string $value
*/
public function setValue($value)
{
$this->value = $value;
}
/**
* Gets the value parameter for this validator rule.
* @return string
*/
public function getValue()
{
return $this->value;
}
/**
* Sets the message that will be displayed to the user if validation fails.
* This message may be a Gettext msgid (if translation="gettext") or some other
* id for an alternative not-yet-supported translation system. It may also
* be a simple, single-language string.
* @param string $message
* @see setTranslation()
*/
public function setMessage($message)
{
$this->message = $message;
}
/**
* Gets the message that will be displayed to the user if validation fails.
* This message may be a Gettext msgid (if translation="gettext") or some other
* id for an alternative not-yet-supported translation system. It may also
* be a simple, single-language string.
* @return string
* @see setTranslation()
*/
public function getMessage()
{
$message = str_replace('${value}', $this->getValue(), $this->message);
return $message;
}
/**
* Create XML (string) representation of this object.
* @return string
*/
public function toString()
{
$result = "<rule name=\"" . $this->getName() . "\" ";
if ($this->getValue() !== null) {
$result .= "value=\"" . $this->getValue(). "\" ";
}
if ($this->getClass() !== null) {
$result .= "class=\"".$this->getClass()."\" ";
}
$result .= "message=\"" . $this->getMessage() . "\" ";
$result .= "/>\n";
return $result;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,69 @@
<?php
/*
* $Id: Unique.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
include_once 'propel/engine/database/model/Index.php';
/**
* Information about unique columns of a table. This class assumes
* that in the underlying RDBMS, unique constraints and unique indices
* are roughly equivalent. For example, adding a unique constraint to
* a column also creates an index on that column (this is known to be
* true for MySQL and Oracle).
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Jason van Zyl <jvanzyl@apache.org> (Torque)
* @author Daniel Rall <dlr@collab.net> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class Unique extends Index {
/**
* Default constructor.
*/
public function __construct(Table $table, $indexColumns = array())
{
}
/**
* Returns <code>true</code>.
*/
public function isUnique()
{
return true;
}
/**
* String representation of the index. This is an xml representation.
*/
public function toString()
{
$result = " <unique name=\"" . $this->getName() . "\">\n";
$columns = $this->getColumns();
for ($i=0, $size=count($columns); $i < $size; $i++) {
$result .= " <unique-column name=\""
. $columns[$i]
. "\"/>\n";
}
$result .= " </unique>\n";
return $result;
}
}

View File

@ -0,0 +1,186 @@
<?php
/*
* $Id: Validator.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/database/model/XMLElement.php';
include_once 'propel/engine/EngineException.php';
include_once 'propel/engine/database/model/PropelTypes.php';
include_once 'propel/engine/database/model/Rule.php';
/**
* Validator.
*
* @author Michael Aichler <aichler@mediacluster.de> (Propel)
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
class Validator extends XMLElement {
const TRANSLATE_NONE = "none";
const TRANSLATE_GETTEXT = "gettext";
private $columnName;
private $column;
private $ruleList;
private $translate;
private $table;
/**
* Creates a new column and set the name
*
* @param name validator name
*/
public function __construct()
{
$this->ruleList = array();
}
/**
* Sets up the Validator object based on the attributes that were passed to loadFromXML().
* @see parent::loadFromXML()
*/
protected function setupObject()
{
$this->columnName = $this->getAttribute("column");
$this->translate = $this->getAttribute("translate", $this->getTable()->getDatabase()->getDefaultTranslateMethod());;
}
/**
* Add a Rule to this validator.
* Supports two signatures:
* - addRule(Rule $rule)
* - addRule(array $attribs)
* @param mixed $data Rule object or XML attribs (array) from <rule/> element.
* @return Rule The added Rule.
*/
public function addRule($data)
{
if ($data instanceof Rule) {
$rule = $data; // alias
$rule->setValidator($this);
$this->ruleList[] = $rule;
return $rule;
}
else {
$rule = new Rule();
$rule->setValidator($this);
$rule->loadFromXML($data);
return $this->addRule($rule); // call self w/ different param
}
}
/**
* Gets an array of all added rules for this validator.
* @return array Rule[]
*/
public function getRules()
{
return $this->ruleList;
}
/**
* Gets the name of the column that this Validator applies to.
* @return string
*/
public function getColumnName()
{
return $this->columnName;
}
/**
* Sets the Column object that this validator applies to.
* @param Column $column
* @see Table::addValidator()
*/
public function setColumn(Column $column)
{
$this->column = $column;
}
/**
* Gets the Column object that this validator applies to.
* @return Column
*/
public function getColumn()
{
return $this->column;
}
/**
* Set the owning Table.
* @param Table $table
*/
public function setTable(Table $table)
{
$this->table = $table;
}
/**
* Get the owning Table.
* @return Table
*/
public function getTable()
{
return $this->table;
}
/**
* Set the translation mode to use for the message.
* Currently only "gettext" and "none" are supported. The default is "none".
* @param string $method Translation method ("gettext", "none").
*/
public function setTranslate($method)
{
$this->translate = $method;
}
/**
* Get the translation mode to use for the message.
* Currently only "gettext" and "none" are supported. The default is "none".
* @return string Translation method ("gettext", "none").
*/
public function getTranslate()
{
return $this->translate;
}
/**
* Gets XML (string) representation of this Validator.
* @return string
*/
public function toString()
{
$result = "<validator column=\"" . $this->columnName . "\"";
if ($this->translate !== null) {
$result .= " translate=\"".$this->translate."\"";
}
$result .= ">\n";
if ($this->ruleList !== null) {
for($i=0,$_i=count($this->ruleList); $i < $_i; $i++) {
$result .= $this->ruleList[$i]->toString();
}
}
$result .= "</validator>\n";
return $result;
}
}

View File

@ -0,0 +1,141 @@
<?php
/*
* $Id: XMLElement.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
/**
* An abstract class for elements represented by XML tags (e.g. Column, Table).
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 536 $
* @package propel.engine.database.model
*/
abstract class XMLElement {
protected $attributes = array();
protected $vendorSpecificInfo = array();
/**
* Replaces the old loadFromXML() so that we can use loadFromXML() to load the attribs into the class.
*/
abstract protected function setupObject();
/**
* This is the entry point method for loading data from XML.
* It calls a setupObject() method that must be implemented by the child class.
* @param array $attributes The attributes for the XML tag.
*/
public function loadFromXML($attributes) {
$this->attributes = array_change_key_case($attributes, CASE_LOWER);
$this->setupObject();
}
/**
* Returns the assoc array of attributes.
* All attribute names (keys) are lowercase.
* @return array
*/
public function getAttributes() {
return $this->attributes;
}
/**
* Gets a particular attribute by [case-insensitive] name.
* If attribute is not set then the $defaultValue is returned.
* @param string $name The [case-insensitive] name of the attribute to lookup.
* @param mixed $defaultValue The default value to use in case the attribute is not set.
* @return mixed The value of the attribute or $defaultValue if not set.
*/
public function getAttribute($name, $defaultValue = null) {
$name = strtolower($name);
if (isset($this->attributes[$name])) {
return $this->attributes[$name];
} else {
return $defaultValue;
}
}
/**
* Converts value specified in XML to a boolean value.
* This is to support the default value when used w/ a boolean column.
* @return value
*/
protected function booleanValue($val) {
if (is_numeric($val)) {
return (bool) $val;
} else {
return (in_array(strtolower($val), array('true', 't', 'y', 'yes'), true) ? true : false);
}
}
/**
* Sets vendor specific parameter that applies to this object.
* @param string $name
* @param string $value
*/
public function setVendorParameter($name, $value)
{
$this->vendorSpecificInfo[$name] = $value;
}
/**
* Whether specified vendor specific information is set.
* @param string $name
* @return boolean
*/
public function hasVendorParameter($name)
{
return isset($this->vendorSpecificInfo[$name]);
}
/**
* Returns specified vendor specific information is set.
* @param string $name
* @return string
*/
public function getVendorParameter($name)
{
if (isset($this->vendorSpecificInfo[$name])) {
return $this->vendorSpecificInfo[$name];
}
return null; // just to be explicit
}
/**
* Sets vendor specific information for this object.
* @param array $info
*/
public function setVendorSpecificInfo($info)
{
$this->vendorSpecificInfo = $info;
}
/**
* Retrieves vendor specific information for this object.
* @return array
*/
public function getVendorSpecificInfo()
{
return $this->vendorSpecificInfo;
}
}

View File

@ -0,0 +1,420 @@
<?php
/*
* $Id: XmlToAppData.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
include_once 'propel/engine/database/model/AppData.php';
// Phing dependencies
require_once 'phing/parser/AbstractHandler.php';
include_once 'phing/system/io/FileReader.php';
/**
* A class that is used to parse an input xml schema file and creates an AppData
* PHP object.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Leon Messerschmidt <leon@opticode.co.za> (Torque)
* @author Jason van Zyl <jvanzyl@apache.org> (Torque)
* @author Martin Poeschl <mpoeschl@marmot.at> (Torque)
* @author Daniel Rall <dlr@collab.net> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.transform
*/
class XmlToAppData extends AbstractHandler {
/** enables debug output */
const DEBUG = false;
private $app;
private $platform;
private $currDB;
private $currTable;
private $currColumn;
private $currFK;
private $currIndex;
private $currUnique;
private $currValidator;
private $currVendorObject;
private $isForReferenceOnly;
private $currentPackage;
private $currentXmlFile;
private $defaultPackage;
private $encoding;
/** two-dimensional array,
first dimension is for schemas(key is the path to the schema file),
second is for tags within the schema */
private $schemasTagsStack = array();
public $parser;
/**
* Creates a new instance for the specified database type.
*
* @param Platform $platform The type of database for the application.
* @param string $defaultPackage the default PHP package used for the om
* @param string $encoding The database encoding.
*/
public function __construct(Platform $platform, $defaultPackage, $encoding = 'iso-8859-1')
{
$this->app = new AppData($platform);
$this->platform = $platform;
$this->defaultPackage = $defaultPackage;
$this->firstPass = true;
$this->encoding = $encoding;
}
/**
* Parses a XML input file and returns a newly created and
* populated AppData structure.
*
* @param string $xmlFile The input file to parse.
* @return AppData populated by <code>xmlFile</code>.
*/
public function parseFile($xmlFile)
{
// we don't want infinite recursion
if($this->isAlreadyParsed($xmlFile)) {
return;
}
$domDocument = new DomDocument('1.0', 'UTF-8');
$domDocument->load($xmlFile);
// store current schema file path
$this->schemasTagsStack[$xmlFile] = array();
$this->currentXmlFile = $xmlFile;
try {
$fr = new FileReader($xmlFile);
} catch (Exception $e) {
$f = new PhingFile($xmlFile);
throw new Exception("XML File not found: " . $f->getAbsolutePath());
}
$br = new BufferedReader($fr);
$this->parser = new ExpatParser($br);
$this->parser->parserSetOption(XML_OPTION_CASE_FOLDING, 0);
$this->parser->setHandler($this);
try {
$this->parser->parse();
} catch (Exception $e) {
$br->close();
throw $e;
}
$br->close();
array_pop($this->schemasTagsStack);
return $this->app;
}
/**
* Handles opening elements of the xml file.
*
* @param string $uri
* @param string $localName The local name (without prefix), or the empty string if
* Namespace processing is not being performed.
* @param string $rawName The qualified name (with prefix), or the empty string if
* qualified names are not available.
* @param string $attributes The specified or defaulted attributes
*/
public function startElement($name, $attributes) {
try {
$parentTag = $this->peekCurrentSchemaTag();
if ($parentTag === false) {
switch($name) {
case "database":
if ($this->isExternalSchema()) {
$this->currentPackage = @$attributes["package"];
if ($this->currentPackage === null) {
$this->currentPackage = $this->defaultPackage;
}
} else {
$this->currDB = $this->app->addDatabase($attributes);
}
break;
default:
$this->_throwInvalidTagException($name);
}
} elseif ($parentTag == "database") {
switch($name) {
case "external-schema":
$xmlFile = @$attributes["filename"];
//"referenceOnly" attribute is valid in the main schema XML file only,
//and it's ingnored in the nested external-schemas
if(!$this->isExternalSchema()) {
$isForRefOnly = @$attributes["referenceOnly"];
$this->isForReferenceOnly = ($isForRefOnly !== null ? (strtolower($isForRefOnly) === "true") : true); // defaults to TRUE
}
if ($xmlFile{0} != '/') {
$f = new PhingFile($this->currentXmlFile);
$xf = new PhingFile($f->getParent(), $xmlFile);
$xmlFile = $xf->getPath();
}
$this->parseFile($xmlFile);
break;
case "domain":
$this->currDB->addDomain($attributes);
break;
case "table":
$this->currTable = $this->currDB->addTable($attributes);
if ($this->isExternalSchema()) {
$this->currTable->setForReferenceOnly($this->isForReferenceOnly);
$this->currTable->setPackage($this->currentPackage);
}
break;
case "vendor":
$this->currVendorObject = new ObjectWithVendorSpecificData($this->currDB, $attributes['type']);
break;
default:
$this->_throwInvalidTagException($name);
}
} elseif ($parentTag == "table") {
switch($name) {
case "column":
$this->currColumn = $this->currTable->addColumn($attributes);
break;
case "foreign-key":
$this->currFK = $this->currTable->addForeignKey($attributes);
break;
case "index":
$this->currIndex = $this->currTable->addIndex($attributes);
break;
case "unique":
$this->currUnique = $this->currTable->addUnique($attributes);
break;
case "vendor":
$this->currVendorObject = new ObjectWithVendorSpecificData($this->currTable, $attributes['type']);
break;
case "validator":
$this->currValidator = $this->currTable->addValidator($attributes);
break;
case "id-method-parameter":
$this->currTable->addIdMethodParameter($attributes);
break;
default:
$this->_throwInvalidTagException($name);
}
} elseif ($parentTag == "column") {
switch($name) {
case "inheritance":
$this->currColumn->addInheritance($attributes);
break;
case "vendor":
$this->currVendorObject = new ObjectWithVendorSpecificData($this->currColumn, $attributes['type']);
break;
default:
$this->_throwInvalidTagException($name);
}
} elseif ($parentTag == "foreign-key") {
switch($name) {
case "reference":
$this->currFK->addReference($attributes);
break;
case "vendor":
$this->currVendorObject = new ObjectWithVendorSpecificData($this->currFK, $attributes['type']);
break;
default:
$this->_throwInvalidTagException($name);
}
} elseif ($parentTag == "index") {
switch($name) {
case "index-column":
$this->currIndex->addColumn($attributes);
break;
case "vendor":
$this->currVendorObject = new ObjectWithVendorSpecificData($this->currIndex, $attributes['type']);
break;
default:
$this->_throwInvalidTagException($name);
}
} elseif ($parentTag == "unique") {
switch($name) {
case "unique-column":
$this->currUnique->addColumn($attributes);
break;
case "vendor":
$this->currVendorObject = new ObjectWithVendorSpecificData($this->currUnique, $attributes['type']);
break;
default:
$this->_throwInvalidTagException($name);
}
} elseif ($parentTag == "validator") {
switch($name) {
case "rule":
$this->currValidator->addRule($attributes);
break;
default:
$this->_throwInvalidTagException($name);
}
} elseif ($parentTag == "vendor") {
switch($name) {
case "parameter":
if($this->currVendorObject->isCompatible($this->platform->getDatabaseType())) {
$this->currVendorObject->setVendorParameter($attributes['name'], iconv('utf-8',$this->encoding, $attributes['value']));
}
break;
default:
$this->_throwInvalidTagException($name);
}
} else {
// it must be an invalid tag
$this->_throwInvalidTagException($name);
}
$this->pushCurrentSchemaTag($name);
} catch (BuildException $e) {
throw $e;
} catch (Exception $e) {
echo $e;
echo "\n";
throw $e;
}
}
function _throwInvalidTagException($tag_name)
{
throw new BuildException("Unexpected tag <" . $tag_name . ">", $this->parser->getLocation());
}
/**
* Handles closing elements of the xml file.
*
* @param uri
* @param localName The local name (without prefix), or the empty string if
* Namespace processing is not being performed.
* @param rawName The qualified name (with prefix), or the empty string if
* qualified names are not available.
*/
public function endElement($name)
{
if (self::DEBUG) {
print("endElement(" . $name . ") called\n");
}
$this->popCurrentSchemaTag();
}
protected function peekCurrentSchemaTag()
{
$keys = array_keys($this->schemasTagsStack);
return end($this->schemasTagsStack[end($keys)]);
}
protected function popCurrentSchemaTag()
{
$keys = array_keys($this->schemasTagsStack);
array_pop($this->schemasTagsStack[end($keys)]);
}
protected function pushCurrentSchemaTag($tag)
{
$keys = array_keys($this->schemasTagsStack);
$this->schemasTagsStack[end($keys)][] = $tag;
}
protected function isExternalSchema()
{
return (sizeof($this->schemasTagsStack) > 1);
}
protected function isAlreadyParsed($filePath)
{
return isset($this->schemasTagsStack[$filePath]);
}
}
/**
* Utility class used for objects with vendor data.
*
* @package propel.engine.database.transform
*/
class ObjectWithVendorSpecificData
{
protected $object;
protected $vendorType;
public function __construct($object, $vendorType)
{
$this->object = $object;
$this->vendorType = $vendorType;
}
public function isCompatible($type)
{
return ($this->vendorType == $type);
}
public function setVendorParameter($name, $value)
{
$this->object->setVendorParameter($name, $value);
}
}

View File

@ -0,0 +1,189 @@
<?php
/*
* $Id: XmlToData.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'phing/parser/AbstractHandler.php';
/**
* A Class that is used to parse an input xml schema file and creates an
* AppData object.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Leon Messerschmidt <leon@opticode.co.za> (Torque)
* @author Jason van Zyl <jvanzyl@apache.org> (Torque)
* @author Martin Poeschl <mpoeschl@marmot.at> (Torque)
* @author Fedor Karpelevitch <fedor.karpelevitch@home.com> (Torque)
* @version $Revision: 536 $
* @package propel.engine.database.transform
*/
class XmlToData extends AbstractHandler {
private $database;
private $data;
private $encoding;
public $parser;
const DEBUG = false;
/**
* Construct new XmlToData class.
*
* This class is passed the Database object so that it knows what to expect from
* the XML file.
*
* @param Database $database
*/
public function __construct(Database $database, $encoding = 'iso-8859-1')
{
$this->database = $database;
$this->encoding = $encoding;
}
/**
*
*/
public function parseFile($xmlFile)
{
try {
$this->data = array();
try {
$fr = new FileReader($xmlFile);
} catch (Exception $e) {
$f = new PhingFile($xmlFile);
throw new BuildException("XML File not found: " . $f->getAbsolutePath());
}
$br = new BufferedReader($fr);
$this->parser = new ExpatParser($br);
$this->parser->parserSetOption(XML_OPTION_CASE_FOLDING, 0);
$this->parser->setHandler($this);
try {
$this->parser->parse();
} catch (Exception $e) {
print $e->getMessage() . "\n";
$br->close();
}
$br->close();
} catch (Exception $e) {
print $e->getMessage() . "\n";
print $e->getTraceAsString();
}
return $this->data;
}
/**
* Handles opening elements of the xml file.
*/
public function startElement($name, $attributes)
{
try {
if ($name == "dataset") {
// we don't do anything w/ <dataset> tag right now.
} else {
$table = $this->database->getTableByPhpName($name);
$this->columnValues = array();
foreach($attributes as $name => $value) {
$col = $table->getColumnByPhpName($name);
$this->columnValues[] = new ColumnValue($col, iconv('utf-8',$this->encoding, $value));
}
$this->data[] = new DataRow($table, $this->columnValues);
}
} catch (Exception $e) {
print $e;
throw $e;
}
}
/**
* Handles closing elements of the xml file.
*
* @param $name The local name (without prefix), or the empty string if
* Namespace processing is not being performed.
*/
public function endElement($name)
{
if (self::DEBUG) {
print("endElement(" . $name . ") called\n");
}
}
} // XmlToData
/**
* "inner class"
* @package propel.engine.database.transform
*/
class DataRow
{
private $table;
private $columnValues;
public function __construct(Table $table, $columnValues)
{
$this->table = $table;
$this->columnValues = $columnValues;
}
public function getTable()
{
return $this->table;
}
public function getColumnValues()
{
return $this->columnValues;
}
}
/**
* "inner" class
* @package propel.engine.database.transform
*/
class ColumnValue {
private $col;
private $val;
public function __construct(Column $col, $val)
{
$this->col = $col;
$this->val = $val;
}
public function getColumn()
{
return $this->col;
}
public function getValue()
{
return $this->val;
}
}

View File

@ -0,0 +1,169 @@
<?php
/*
* $Id: DefaultPlatform.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/platform/Platform.php';
include_once 'propel/engine/database/model/Domain.php';
/**
* Default implementation for the Platform interface.
*
* @author Martin Poeschl <mpoeschl@marmot.at> (Torque)
* @version $Revision: 536 $
* @package propel.engine.platform
*/
class DefaultPlatform implements Platform {
private $schemaDomainMap;
/**
* Default constructor.
*/
public function __construct()
{
$this->initialize();
}
protected function initialize()
{
$this->schemaDomainMap = array();
foreach(PropelTypes::getPropelTypes() as $type) {
$this->schemaDomainMap[$type] = new Domain($type);
}
$this->schemaDomainMap[PropelTypes::BU_DATE] = new Domain("DATE");
$this->schemaDomainMap[PropelTypes::BU_TIMESTAMP] = new Domain("TIMESTAMP");
$this->schemaDomainMap[PropelTypes::BOOLEAN] = new Domain("INTEGER");
}
protected function setSchemaDomainMapping(Domain $domain)
{
$this->schemaDomainMap[$domain->getType()] = $domain;
}
/**
* Returns the short name of the database type that this platform represents.
* For example MysqlPlatform->getDatabaseType() returns 'mysql'.
* @return string
*/
public function getDatabaseType()
{
$clazz = get_class($this);
$pos = strpos($clazz, 'Platform');
return strtolower(substr($clazz,0,$pos));
}
/**
* @see Platform::getMaxColumnNameLength()
*/
public function getMaxColumnNameLength()
{
return 64;
}
/**
* @see Platform::getNativeIdMethod()
*/
public function getNativeIdMethod()
{
return Platform::IDENTITY;
}
/**
* @see Platform::getDomainForType()
*/
public function getDomainForType($propelType)
{
if (!isset($this->schemaDomainMap[$propelType])) {
throw new EngineException("Cannot map unknown Propel type " . var_export($propelType, true) . " to native database type.");
}
return $this->schemaDomainMap[$propelType];
}
/**
* @return Only produces a SQL fragment if null values are
* disallowed.
* @see Platform::getNullString(boolean)
*/
public function getNullString($notNull)
{
// TODO: Check whether this is true for all DBs. Also verify
// the old Sybase templates.
return ($notNull ? "NOT NULL" : "");
}
/**
* @see Platform::getAutoIncrement()
*/
public function getAutoIncrement()
{
return "IDENTITY";
}
/**
* @see Platform::hasScale(String)
* TODO collect info for all platforms
*/
public function hasScale($sqlType)
{
return true;
}
/**
* @see Platform::hasSize(String)
* TODO collect info for all platforms
*/
public function hasSize($sqlType)
{
return true;
}
/**
* @see Platform::escapeText()
*/
public function escapeText($text)
{
return str_replace("'", "''", $text);
}
/**
* @see Platform::quoteIdentifier()
*/
public function quoteIdentifier($text)
{
return '"' . $text . '"';
}
/**
* @see Platform::supportsNativeDeleteTrigger()
*/
public function supportsNativeDeleteTrigger()
{
return false;
}
/**
* @see Platform::getBooleanString()
*/
public function getBooleanString($b)
{
$b = ($b === true || strtolower($b) === 'true' || $b === 1 || $b === '1' || strtolower($b) === 'y' || strtolower($b) === 'yes');
return ($b ? '1' : '0');
}
}

View File

@ -0,0 +1,99 @@
<?php
/*
* $Id: MssqlPlatform.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/platform/DefaultPlatform.php';
include_once 'propel/engine/database/model/Domain.php';
/**
* MS SQL Platform implementation.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Martin Poeschl <mpoeschl@marmot.at> (Torque)
* @version $Revision: 536 $
* @package propel.engine.platform
*/
class MssqlPlatform extends DefaultPlatform {
/**
* Initializes db specific domain mapping.
*/
protected function initialize()
{
parent::initialize();
$this->setSchemaDomainMapping(new Domain(PropelTypes::INTEGER, "INT"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BOOLEAN, "INT"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::DOUBLE, "FLOAT"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARCHAR, "TEXT"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::CLOB, "TEXT"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::DATE, "DATETIME"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BU_DATE, "DATETIME"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::TIME, "DATETIME"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::TIMESTAMP, "DATETIME"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BU_TIMESTAMP, "DATETIME"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BINARY, "BINARY(7132)"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::VARBINARY, "IMAGE"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARBINARY, "IMAGE"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BLOB, "IMAGE"));
}
/**
* @see Platform#getMaxColumnNameLength()
*/
public function getMaxColumnNameLength()
{
return 128;
}
/**
* @return Explicitly returns <code>NULL</code> if null values are
* allowed (as recomended by Microsoft).
* @see Platform#getNullString(boolean)
*/
public function getNullString($notNull)
{
return ($notNull ? "NOT NULL" : "NULL");
}
/**
* @see Platform::supportsNativeDeleteTrigger()
*/
public function supportsNativeDeleteTrigger()
{
return true;
}
/**
* @see Platform::hasSize(String)
*/
public function hasSize($sqlType)
{
return !("INT" == $sqlType || "TEXT" == $sqlType);
}
/**
* @see Platform::quoteIdentifier()
*/
public function quoteIdentifier($text)
{
return '[' . $text . ']';
}
}

View File

@ -0,0 +1,105 @@
<?php
/*
* $Id: MysqlPlatform.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/platform/DefaultPlatform.php';
/**
* MySql Platform implementation.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Martin Poeschl <mpoeschl@marmot.at> (Torque)
* @version $Revision: 536 $
* @package propel.engine.platform
*/
class MysqlPlatform extends DefaultPlatform {
/**
* Initializes db specific domain mapping.
*/
protected function initialize()
{
parent::initialize();
$this->setSchemaDomainMapping(new Domain(PropelTypes::NUMERIC, "DECIMAL"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARCHAR, "TEXT"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::TIMESTAMP, "DATETIME"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BU_TIMESTAMP, "DATETIME"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BINARY, "BLOB"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::VARBINARY, "MEDIUMBLOB"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARBINARY, "LONGBLOB"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BLOB, "LONGBLOB"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::CLOB, "LONGTEXT"));
}
/**
* @see Platform#getAutoIncrement()
*/
public function getAutoIncrement()
{
return "AUTO_INCREMENT";
}
/**
* @see Platform#getMaxColumnNameLength()
*/
public function getMaxColumnNameLength()
{
return 64;
}
/**
* @see Platform::supportsNativeDeleteTrigger()
*/
public function supportsNativeDeleteTrigger()
{
$usingInnoDB = false;
if(class_exists('DataModelBuilder', false))
{
$usingInnoDB = strtolower(DataModelBuilder::getBuildProperty('mysqlTableType')) == 'innodb';
}
return $usingInnoDB || false;
}
/**
* @see Platform#hasSize(String)
*/
public function hasSize($sqlType) {
return !("MEDIUMTEXT" == $sqlType || "LONGTEXT" == $sqlType
|| "BLOB" == $sqlType || "MEDIUMBLOB" == $sqlType
|| "LONGBLOB" == $sqlType);
}
/**
* Escape the string for RDBMS.
* @param string $text
* @return string
*/
public function escapeText($text) {
return mysql_escape_string($text);
}
/**
* @see Platform::quoteIdentifier()
*/
public function quoteIdentifier($text)
{
return '`' . $text . '`';
}
}

View File

@ -0,0 +1,58 @@
<?php
/*
* $Id: MysqliPlatform.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/platform/MysqlPlatform.php';
/**
* MySql Platform implementation, using new mysqli API.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @version $Revision: 536 $
* @package propel.engine.platform
*/
class MysqliPlatform extends MysqlPlatform {
/**
* Initializes db specific domain mapping.
*/
protected function initialize()
{
parent::initialize();
// HL -- commenting these out, as it turns out that while the date format is fixed
// there is still a special meaning to TIMESTAMP in MySQL 4.1+
// $this->setSchemaDomainMapping(new Domain(PropelTypes::TIMESTAMP, "TIMESTAMP"));
// $this->setSchemaDomainMapping(new Domain(PropelTypes::BU_TIMESTAMP, "TIMESTAMP"));
}
/**
* Escape the string for MySQL.
*
* @param string $text
* @return string
*/
public function escapeText($text) {
// Because mysqli requires open connection, we are using addslashes() here.
// This needs to be fixed in a better way ...
return addslashes($text);
}
}

View File

@ -0,0 +1,89 @@
<?php
/*
* $Id: OraclePlatform.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/platform/DefaultPlatform.php';
/**
* Oracle Platform implementation.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Martin Poeschl <mpoeschl@marmot.at> (Torque)
* @version $Revision: 536 $
* @package propel.engine.platform
*/
class OraclePlatform extends DefaultPlatform {
/**
* Initializes db specific domain mapping.
*/
protected function initialize()
{
parent::initialize();
$this->setSchemaDomainMapping(new Domain(PropelTypes::BOOLEAN, "NUMBER", "1", "0"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::TINYINT, "NUMBER", "3", "0"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::SMALLINT, "NUMBER", "5", "0"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::INTEGER, "NUMBER"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BIGINT, "NUMBER", "20", "0"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::REAL, "NUMBER"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::DOUBLE, "FLOAT"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::DECIMAL, "NUMBER"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::NUMERIC, "NUMBER"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::VARCHAR, "VARCHAR2"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARCHAR, "VARCHAR2", "2000"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::TIME, "DATE"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::TIMESTAMP, "DATE"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BINARY, "LONG RAW"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::VARBINARY, "BLOB"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARBINARY, "LONG RAW"));
}
/**
* @see Platform#getMaxColumnNameLength()
*/
public function getMaxColumnNameLength()
{
return 30;
}
/**
* @see Platform#getNativeIdMethod()
*/
public function getNativeIdMethod()
{
return Platform::SEQUENCE;
}
/**
* @see Platform#getAutoIncrement()
*/
public function getAutoIncrement()
{
return "";
}
/**
* @see Platform::supportsNativeDeleteTrigger()
*/
public function supportsNativeDeleteTrigger()
{
return true;
}
}

View File

@ -0,0 +1,114 @@
<?php
/*
* $Id: PgsqlPlatform.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/platform/DefaultPlatform.php';
/**
* Postgresql Platform implementation.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Martin Poeschl <mpoeschl@marmot.at> (Torque)
* @version $Revision: 536 $
* @package propel.engine.platform
*/
class PgsqlPlatform extends DefaultPlatform {
/**
* Initializes db specific domain mapping.
*/
protected function initialize()
{
parent::initialize();
$this->setSchemaDomainMapping(new Domain(PropelTypes::BOOLEAN, "BOOLEAN"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::TINYINT, "INT2"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::SMALLINT, "INT2"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BIGINT, "INT8"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::REAL, "FLOAT"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::DOUBLE, "DOUBLE PRECISION"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARCHAR, "TEXT"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BINARY, "BYTEA"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::VARBINARY, "BYTEA"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARBINARY, "BYTEA"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BLOB, "BYTEA"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::CLOB, "TEXT"));
}
/**
* @see Platform#getNativeIdMethod()
*/
public function getNativeIdMethod()
{
return Platform::SEQUENCE;
}
/**
* @see Platform#getAutoIncrement()
*/
public function getAutoIncrement()
{
return "";
}
/**
* @see Platform#getMaxColumnNameLength()
*/
public function getMaxColumnNameLength()
{
return 32;
}
/**
* Escape the string for RDBMS.
* @param string $text
* @return string
*/
public function escapeText($text) {
return pg_escape_string($text);
}
/**
* @see Platform::getBooleanString()
*/
public function getBooleanString($b)
{
// parent method does the checking for allowes tring
// representations & returns integer
$b = parent::getBooleanString($b);
return ($b ? "'t'" : "'f'");
}
/**
* @see Platform::supportsNativeDeleteTrigger()
*/
public function supportsNativeDeleteTrigger()
{
return true;
}
/**
* @see Platform::hasSize(String)
* TODO collect info for all platforms
*/
public function hasSize($sqlType)
{
return !("BYTEA" == $sqlType || "TEXT" == $sqlType);
}
}

View File

@ -0,0 +1,128 @@
<?php
/*
* $Id: Platform.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
/**
* Interface for RDBMS platform specific behaviour.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Martin Poeschl <mpoeschl@marmot.at> (Torque)
* @version $Revision: 536 $
* @package propel.engine.platform
*/
interface Platform {
/** constant for native id method */
const IDENTITY = "identity";
/** constant for native id method */
const SEQUENCE = "sequence";
/**
* Returns the short name of the database type that this platform represents.
* For example MysqlPlatform->getDatabaseType() returns 'mysql'.
* @return string
*/
public function getDatabaseType();
/**
* Returns the native IdMethod (sequence|identity)
*
* @return string The native IdMethod (Platform:IDENTITY, Platform::SEQUENCE).
*/
public function getNativeIdMethod();
/**
* Returns the max column length supported by the db.
*
* @return int The max column length
*/
public function getMaxColumnNameLength();
/**
* Returns the db specific domain for a jdbcType.
*
* @param string $creoleType the creole type name.
* @return Domain The db specific domain.
*/
public function getDomainForType($creoleType);
/**
* @return string The RDBMS-specific SQL fragment for <code>NULL</code>
* or <code>NOT NULL</code>.
*/
public function getNullString($notNull);
/**
* @return The RDBMS-specific SQL fragment for autoincrement.
*/
public function getAutoIncrement();
/**
* Returns if the RDBMS-specific SQL type has a size attribute.
*
* @param string $sqlType the SQL type
* @return boolean True if the type has a size attribute
*/
public function hasSize($sqlType);
/**
* Returns if the RDBMS-specific SQL type has a scale attribute.
*
* @param string $sqlType the SQL type
* @return boolean True if the type has a scale attribute
*/
public function hasScale($sqlType);
/**
* Escape the string for RDBMS.
* @param string $text
* @return string
*/
public function escapeText($text);
/**
* Quotes identifiers used in database SQL.
* @param string $text
* @return string Quoted identifier.
*/
public function quoteIdentifier($text);
/**
* Whether RDBMS supports native ON DELETE triggers (e.g. ON DELETE CASCADE).
* @return boolean
*/
public function supportsNativeDeleteTrigger();
/**
* Returns the boolean value for the RDBMS.
*
* This value should match the boolean value that is set
* when using Creole's PreparedStatement::setBoolean().
*
* This function is used to set default column values when building
* SQL.
*
* @param mixed $tf A boolean or string representation of boolean ('y', 'true').
* @return mixed
*/
public function getBooleanString($tf);
}

View File

@ -0,0 +1,92 @@
<?php
/*
* $Id: SqlitePlatform.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/engine/platform/DefaultPlatform.php';
/**
* SQLite Platform implementation.
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 536 $
* @package propel.engine.platform
*/
class SqlitePlatform extends DefaultPlatform {
/**
* Initializes db specific domain mapping.
*/
protected function initialize()
{
parent::initialize();
$this->setSchemaDomainMapping(new Domain(PropelTypes::NUMERIC, "DECIMAL"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARCHAR, "MEDIUMTEXT"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::DATE, "DATETIME"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BINARY, "BLOB"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::VARBINARY, "MEDIUMBLOB"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::LONGVARBINARY, "LONGBLOB"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::BLOB, "LONGBLOB"));
$this->setSchemaDomainMapping(new Domain(PropelTypes::CLOB, "LONGTEXT"));
}
/**
* @see Platform#getAutoIncrement()
* @link http://www.sqlite.org/autoinc.html
*/
public function getAutoIncrement()
{
return "PRIMARY KEY";
}
/**
* @see Platform#getMaxColumnNameLength()
*/
public function getMaxColumnNameLength()
{
return 1024;
}
/**
* @see Platform#hasSize(String)
*/
public function hasSize($sqlType) {
return !("MEDIUMTEXT" == $sqlType || "LONGTEXT" == $sqlType
|| "BLOB" == $sqlType || "MEDIUMBLOB" == $sqlType
|| "LONGBLOB" == $sqlType);
}
/**
* Escape the string for RDBMS.
* @param string $text
* @return string
*/
public function escapeText($text) {
return sqlite_escape_string($text);
}
/**
* @see Platform::quoteIdentifier()
*/
public function quoteIdentifier($text)
{
return '[' . $text . ']';
}
}

View File

@ -0,0 +1,635 @@
<?php
/*
* $Id: AbstractPropelDataModelTask.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
//include_once 'phing/tasks/ext/CapsuleTask.php';
require_once 'phing/Task.php';
include_once 'propel/engine/database/model/AppData.php';
include_once 'propel/engine/database/model/Database.php';
include_once 'propel/engine/database/transform/XmlToAppData.php';
/**
* An abstract base Propel task to perform work related to the XML schema file.
*
* The subclasses invoke templates to do the actual writing of the resulting files.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Jason van Zyl <jvanzyl@zenplex.com> (Torque)
* @author Daniel Rall <dlr@finemaltcoding.com> (Torque)
* @package propel.phing
*/
abstract class AbstractPropelDataModelTask extends Task {
/**
* Fileset of XML schemas which represent our data models.
* @var array Fileset[]
*/
protected $schemaFilesets = array();
/**
* Data models that we collect. One from each XML schema file.
*/
protected $dataModels = array();
/**
* Have datamodels been initialized?
* @var boolean
*/
private $dataModelsLoaded = false;
/**
* Map of data model name to database name.
* Should probably stick to the convention
* of them being the same but I know right now
* in a lot of cases they won't be.
*/
protected $dataModelDbMap;
/**
* Hashtable containing the names of all the databases
* in our collection of schemas.
*/
protected $databaseNames; // doesn't seem to be used anywhere
/**
* The target database(s) we are generating SQL
* for. Right now we can only deal with a single
* target, but we will support multiple targets
* soon.
*/
protected $targetDatabase;
/**
* DB encoding to use for XmlToAppData object
*/
protected $dbEncoding = 'iso-8859-1';
/**
* Target PHP package to place the generated files in.
*/
protected $targetPackage;
/**
* @var Mapper
*/
protected $mapperElement;
/**
* Destination directory for results of template scripts.
* @var PhingFile
*/
protected $outputDirectory;
/**
* Path where Capsule looks for templates.
* @var PhingFile
*/
protected $templatePath;
/**
* Whether to package the datamodels or not
* @var PhingFile
*/
protected $packageObjectModel;
/**
* Whether to perform validation (XSD) on the schema.xml file(s).
* @var boolean
*/
protected $validate;
/**
* The XSD schema file to use for validation.
* @var PhingFile
*/
protected $xsdFile;
/**
* XSL file to use to normalize (or otherwise transform) schema before validation.
* @var PhingFile
*/
protected $xslFile;
/**
* Return the data models that have been
* processed.
*
* @return List data models
*/
public function getDataModels()
{
if (!$this->dataModelsLoaded) $this->loadDataModels();
return $this->dataModels;
}
/**
* Return the data model to database name map.
*
* @return Hashtable data model name to database name map.
*/
public function getDataModelDbMap()
{
if (!$this->dataModelsLoaded) $this->loadDataModels();
return $this->dataModelDbMap;
}
/**
* Adds a set of xml schema files (nested fileset attribute).
*
* @param set a Set of xml schema files
*/
public function addSchemaFileset(Fileset $set)
{
$this->schemaFilesets[] = $set;
}
/**
* Get the current target database.
*
* @return String target database(s)
*/
public function getTargetDatabase()
{
return $this->targetDatabase;
}
/**
* Set the current target database. (e.g. mysql, oracle, ..)
*
* @param v target database(s)
*/
public function setTargetDatabase($v)
{
$this->targetDatabase = $v;
}
/**
* Get the current target package.
*
* @return string target PHP package.
*/
public function getTargetPackage()
{
return $this->targetPackage;
}
/**
* Set the current target package. This is where generated PHP classes will
* live.
*
* @param string $v target PHP package.
*/
public function setTargetPackage($v)
{
$this->targetPackage = $v;
}
/**
* Set the packageObjectModel switch on/off
*
* @param string $v The build.property packageObjectModel
*/
public function setPackageObjectModel($v)
{
$this->packageObjectModel = ($v === '1' ? true : false);
}
/**
* Set whether to perform validation on the datamodel schema.xml file(s).
* @param boolean $v
*/
public function setValidate($v)
{
$this->validate = $v;
}
/**
* Set the XSD schema to use for validation of any datamodel schema.xml file(s).
* @param $v PhingFile
*/
public function setXsd(PhingFile $v)
{
$this->xsdFile = $v;
}
/**
* Set the normalization XSLT to use to transform datamodel schema.xml file(s) before validation and parsing.
* @param $v PhingFile
*/
public function setXsl(PhingFile $v)
{
$this->xslFile = $v;
}
/**
* [REQUIRED] Set the path where Capsule will look
* for templates using the file template
* loader.
* @return void
* @throws Exception
*/
public function setTemplatePath($templatePath) {
$resolvedPath = "";
$tok = strtok($templatePath, ",");
while ( $tok ) {
// resolve relative path from basedir and leave
// absolute path untouched.
$fullPath = $this->project->resolveFile($tok);
$cpath = $fullPath->getCanonicalPath();
if ($cpath === false) {
$this->log("Template directory does not exist: " . $fullPath->getAbsolutePath());
} else {
$resolvedPath .= $cpath;
}
$tok = strtok(",");
if ( $tok ) {
$resolvedPath .= ",";
}
}
$this->templatePath = $resolvedPath;
}
/**
* Get the path where Velocity will look
* for templates using the file template
* loader.
* @return string
*/
public function getTemplatePath() {
return $this->templatePath;
}
/**
* [REQUIRED] Set the output directory. It will be
* created if it doesn't exist.
* @param PhingFile $outputDirectory
* @return void
* @throws Exception
*/
public function setOutputDirectory(PhingFile $outputDirectory) {
try {
if (!$outputDirectory->exists()) {
$this->log("Output directory does not exist, creating: " . $outputDirectory->getPath(),PROJECT_MSG_VERBOSE);
if (!$outputDirectory->mkdirs()) {
throw new IOException("Unable to create Ouptut directory: " . $outputDirectory->getAbsolutePath());
}
}
$this->outputDirectory = $outputDirectory->getCanonicalPath();
} catch (IOException $ioe) {
throw new BuildException($ioe);
}
}
/**
* Set the current target database encoding.
*
* @param v target database encoding
*/
public function setDbEncoding($v)
{
$this->dbEncoding = $v;
}
/**
* Get the output directory.
* @return string
*/
public function getOutputDirectory() {
return $this->outputDirectory;
}
/**
* Nested creator, creates one Mapper for this task.
*
* @return Mapper The created Mapper type object.
* @throws BuildException
*/
public function createMapper() {
if ($this->mapperElement !== null) {
throw new BuildException("Cannot define more than one mapper.", $this->location);
}
$this->mapperElement = new Mapper($this->project);
return $this->mapperElement;
}
/**
* Maps the passed in name to a new filename & returns resolved File object.
* @param string $from
* @return PhingFile Resolved File object.
* @throws BuilException - if no Mapper element se
* - if unable to map new filename.
*/
protected function getMappedFile($from)
{
if(!$this->mapperElement) {
throw new BuildException("This task requires you to use a <mapper/> element to describe how filename changes should be handled.");
}
$mapper = $this->mapperElement->getImplementation();
$mapped = $mapper->main($from);
if (!$mapped) {
throw new BuildException("Cannot create new filename based on: " . $from);
}
// Mappers always return arrays since it's possible for some mappers to map to multiple names.
$outFilename = array_shift($mapped);
$outFile = new PhingFile($this->getOutputDirectory(), $outFilename);
return $outFile;
}
/**
* Get the Platform class based on the target database type.
* @return Platform Class that implements the Platform interface.
*/
protected function getPlatformForTargetDatabase()
{
$classpath = $this->getPropelProperty("platformClass");
if (empty($classpath)) {
throw new BuildException("Unable to find class path for '$propname' property.");
}
// This is a slight hack to workaround camel case inconsistencies for the DDL classes.
// Basically, we want to turn ?.?.?.sqliteDDLBuilder into ?.?.?.SqliteDDLBuilder
$lastdotpos = strrpos($classpath, '.');
if ($lastdotpos) $classpath{$lastdotpos+1} = strtoupper($classpath{$lastdotpos+1});
else ucfirst($classpath);
if (empty($classpath)) {
throw new BuildException("Unable to find class path for '$propname' property.");
}
$clazz = Phing::import($classpath);
return new $clazz();
}
/**
* Gets all matching XML schema files and loads them into data models for class.
* @return void
*/
protected function loadDataModels()
{
$ads = array();
// Get all matched files from schemaFilesets
foreach($this->schemaFilesets as $fs) {
$ds = $fs->getDirectoryScanner($this->project);
$srcDir = $fs->getDir($this->project);
$dataModelFiles = $ds->getIncludedFiles();
$platform = $this->getPlatformForTargetDatabase();
// Make a transaction for each file
foreach($dataModelFiles as $dmFilename) {
$this->log("Processing: ".$dmFilename);
$xmlFile = new PhingFile($srcDir, $dmFilename);
$dom = new DomDocument('1.0', 'UTF-8');
$dom->load($xmlFile->getAbsolutePath());
// normalize (or transform) the XML document using XSLT
if ($this->xslFile) {
$this->log("Transforming " . $xmlFile->getPath() . " using stylesheet " . $this->xslFile->getPath(), PROJECT_MSG_VERBOSE);
if (!class_exists('XSLTProcessor')) {
$this->log("Could not perform XLST transformation. Make sure PHP has been compiled/configured to support XSLT.", PROJECT_MSG_ERR);
} else {
// normalize the document using normalizer stylesheet
$xsl = new XsltProcessor();
$xsl->importStyleSheet(DomDocument::load($this->xslFile->getAbsolutePath()));
$transformed = $xsl->transformToDoc($dom);
$newXmlFilename = substr($xmlFile->getName(), 0, strrpos($xmlFile->getName(), '.')) . '-transformed.xml';
// now overwrite previous vars to point to newly transformed file
$xmlFile = new PhingFile($srcDir, $newXmlFilename);
$transformed->save($xmlFile->getAbsolutePath());
$this->log("\t- Using new (post-transformation) XML file: " . $xmlFile->getPath(), PROJECT_MSG_VERBOSE);
$dom = new DomDocument('1.0', 'UTF-8');
$dom->load($xmlFile->getAbsolutePath());
}
}
// validate the XML document using XSD schema
if ($this->validate && $this->xsdFile) {
$this->log("Validating XML doc (".$xmlFile->getPath().") using schema file " . $this->xsdFile->getPath(), PROJECT_MSG_VERBOSE);
if (!$dom->schemaValidate($this->xsdFile->getAbsolutePath())) {
throw new BuildException("XML schema file (".$xmlFile->getPath().") does not validate. See warnings above for reasons validation failed (make sure error_reporting is set to show E_WARNING if you don't see any)."); throw new EngineException("XML schema does not validate (using schema file $xsdFile). See warnings above for reasons validation failed (make sure error_reporting is set to show E_WARNING if you don't see any).", $this->getLocation());
}
}
$xmlParser = new XmlToAppData($platform, $this->getTargetPackage(), $this->dbEncoding);
$ad = $xmlParser->parseFile($xmlFile->getAbsolutePath());
$ad->setName($dmFilename); // <-- Important: use the original name, not the -transformed name.
$ads[] = $ad;
}
}
if (empty($ads)) {
throw new BuildException("No schema files were found (matching your schema fileset definition).");
}
if (!$this->packageObjectModel) {
$this->dataModels = $ads;
$this->databaseNames = array(); // doesn't seem to be used anywhere
$this->dataModelDbMap = array();
// Different datamodels may state the same database
// names, we just want the unique names of databases.
foreach($this->dataModels as $dm) {
$database = $dm->getDatabase();
$this->dataModelDbMap[$dm->getName()] = $database->getName();
$this->databaseNames[$database->getName()] = $database->getName(); // making list of *unique* dbnames.
}
} else {
$this->joinDatamodels($ads);
$this->dataModels[0]->getDatabases(); // calls doFinalInitialization()
}
$this->dataModelsLoaded = true;
}
/**
* Joins the datamodels collected from schema.xml files into one big datamodel
*
* This applies only when the the packageObjectModel option is set. We need to
* join the datamodels in this case to allow for foreign keys that point to
* tables in different packages.
*
* @param array $ads The datamodels to join
*/
protected function joinDatamodels($ads) {
foreach($ads as $ad) {
$db = $ad->getDatabase(null, false);
$this->dataModelDbMap[$ad->getName()] = $db->getName();
}
foreach ($ads as $addAd) {
$ad = &$this->dataModels[0];
if (!isset($ad)) {
$addAd->setName('JoinedDataModel');
$ad = $addAd;
continue;
}
foreach ($addAd->getDatabases(false) as $addDb) {
$addDbName = $addDb->getName();
if (!$package = $addDb->getPackage()) {
throw new BuildException('No package found for database "' . $addDbName . '" in ' . $addAd->getName() . '. The propel.packageObjectModel property requires the package attribute to be set for each database.');
}
$db = $ad->getDatabase($addDbName, false);
if (!$db) {
$ad->addDatabase($addDb);
continue;
}
foreach ($addDb->getTables() as $addTable) {
$table = $db->getTable($addTable->getName());
if ($table) {
throw new BuildException('Duplicate table found: ' . $addDbName . '.');
}
$db->addTable($addTable);
}
}
}
}
/**
* Creates a new Capsule context with some basic properties set.
* (Capsule is a simple PHP encapsulation system -- aka a php "template" class.)
* @return Capsule
*/
protected function createContext() {
$context = new Capsule();
// Make sure the output directory exists, if it doesn't
// then create it.
$outputDir = new PhingFile($this->outputDirectory);
if (!$outputDir->exists()) {
$this->log("Output directory does not exist, creating: " . $outputDir->getAbsolutePath());
$outputDir->mkdirs();
}
// Place our set of data models into the context along
// with the names of the databases as a convenience for now.
$context->put("targetDatabase", $this->targetDatabase);
$context->put("targetPackage", $this->targetPackage);
$context->put("now", strftime("%c"));
$this->log("Target database type: " . $this->targetDatabase);
$this->log("Target package: " . $this->targetPackage);
$this->log("Using template path: " . $this->templatePath);
$this->log("Output directory: " . $this->outputDirectory);
$context->setTemplatePath($this->templatePath);
$context->setOutputDirectory($this->outputDirectory);
$this->populateContextProperties($context);
return $context;
}
/**
* Fetches the propel.xxx properties from project, renaming the propel.xxx properties to just xxx.
*
* Also, renames any xxx.yyy properties to xxxYyy as PHP doesn't like the xxx.yyy syntax.
*
* @return array Assoc array of properties.
*/
protected function getPropelProperties()
{
$allProps = $this->getProject()->getProperties();
$renamedPropelProps = array();
foreach ($allProps as $key => $propValue) {
if (strpos($key, "propel.") === 0) {
$newKey = substr($key, strlen("propel."));
$j = strpos($newKey, '.');
while ($j !== false) {
$newKey = substr($newKey, 0, $j) . ucfirst(substr($newKey, $j + 1));
$j = strpos($newKey, '.');
}
$renamedPropelProps[$newKey] = $propValue;
}
}
return $renamedPropelProps;
}
/**
* Fetches a single propel.xxx property from project, using "converted" property names.
* @see getPropelProperties()
* @param string $name Name of property to fetch (in converted CamelCase)
* @return string The value of the property (or NULL if not set)
*/
protected function getPropelProperty($name)
{
$props = $this->getPropelProperties();
if (isset($props[$name])) {
return $props[$name];
}
return null; // just to be explicit
}
/**
* Adds the propel.xxx properties to the passed Capsule context, changing names to just xxx.
*
* Also, move xxx.yyy properties to xxxYyy as PHP doesn't like the xxx.yyy syntax.
*
* @param Capsule $context
* @see getPropelProperties()
*/
public function populateContextProperties(Capsule $context)
{
foreach ($this->getPropelProperties() as $key => $propValue) {
$this->log('Adding property ${' . $key . '} to context', PROJECT_MSG_DEBUG);
$context->put($key, $propValue);
}
}
/**
* Checks this class against Basic requrements of any propel datamodel task.
*
* @throws BuildException - if schema fileset was not defined
* - if no output directory was specified
*/
protected function validate()
{
if (empty($this->schemaFilesets)) {
throw new BuildException("You must specify a fileset of XML schemas.", $this->getLocation());
}
// Make sure the output directory is set.
if ($this->outputDirectory === null) {
throw new BuildException("The output directory needs to be defined!", $this->getLocation());
}
if ($this->validate) {
if (!$this->xsdFile) {
throw new BuildException("'validate' set to TRUE, but no XSD specified (use 'xsd' attribute).", $this->getLocation());
}
}
}
}

View File

@ -0,0 +1,777 @@
<?php
/*
* $Id: PropelCreoleTransformTask.php 538 2007-01-10 14:36:03Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
include_once 'creole/Connection.php';
require_once 'phing/Task.php';
/**
* This class generates an XML schema of an existing database from
* Creole metadata.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Jason van Zyl <jvanzyl@periapt.com> (Torque)
* @author Fedor Karpelevitch <fedor.karpelevitch@barra.com> (Torque)
* @version $Revision: 538 $
* @package propel.phing
*/
class PropelCreoleTransformTask extends Task {
/** Name of XML database schema produced. */
protected $xmlSchema;
/** Creole URL. */
protected $dbUrl;
/** Creole driver. */
protected $dbDriver;
/** Creole user name. */
protected $dbUser;
/** Creole password. */
protected $dbPassword;
/** DB encoding to use */
protected $dbEncoding = 'iso-8859-1';
/** DB schema to use. */
protected $dbSchema;
/** parsed DB DSN */
protected $dsn;
/** DOM document produced. */
protected $doc;
/** The document root element. */
protected $databaseNode;
/** Hashtable of columns that have primary keys. */
protected $primaryKeys;
/** Hashtable to track what table a column belongs to. */
// doesn't seem to be used
// protected $columnTableMap;
/** whether to use same name for phpName or not */
protected $samePhpName;
/** whether to add vendor info or not */
protected $addVendorInfo;
/**
* Bitfield to switch on/off which validators will be created.
*
* @var int
*/
protected $validatorBits;
/**
* Collect validatorInfos to create validators.
*
* @var int
*/
protected $validatorInfos;
/**
* Zero bit for no validators
*/
const VALIDATORS_NONE = 0;
/**
* Bit for maxLength validator
*/
const VALIDATORS_MAXLENGTH = 1;
/**
* Bit for maxValue validator
*/
const VALIDATORS_MAXVALUE = 2;
/**
* Bit for type validator
*/
const VALIDATORS_TYPE = 4;
/**
* Bit for required validator
*/
const VALIDATORS_REQUIRED = 8;
/**
* Bit for unique validator
*/
const VALIDATORS_UNIQUE = 16;
/**
* Bit for all validators
*/
const VALIDATORS_ALL = 255;
/**
* Maps validator type tokens to bits
*
* The tokens are used in the propel.addValidators property to define
* which validators are to be added
*
* @static
* @var array
*/
static protected $validatorBitMap = array (
'none' => PropelCreoleTransformTask::VALIDATORS_NONE,
'maxlength' => PropelCreoleTransformTask::VALIDATORS_MAXLENGTH,
'maxvalue' => PropelCreoleTransformTask::VALIDATORS_MAXVALUE,
'type' => PropelCreoleTransformTask::VALIDATORS_TYPE,
'required' => PropelCreoleTransformTask::VALIDATORS_REQUIRED,
'unique' => PropelCreoleTransformTask::VALIDATORS_UNIQUE,
'all' => PropelCreoleTransformTask::VALIDATORS_ALL,
);
/**
* Defines messages that are added to validators
*
* @static
* @var array
*/
static protected $validatorMessages = array (
'maxlength' => array (
'msg' => 'The field %s must be not longer than %s characters.',
'var' => array('colName', 'value')
),
'maxvalue' => array (
'msg' => 'The field %s must be not greater than %s.',
'var' => array('colName', 'value')
),
'type' => array (
'msg' => 'The field %s is not a valid value.',
'var' => array('colName')
),
'required' => array (
'msg' => 'The field %s is required.',
'var' => array('colName')
),
'unique' => array (
'msg' => 'This %s already exists in table %s.',
'var' => array('colName', 'tableName')
),
);
public function getDbSchema()
{
return $this->dbSchema;
}
public function setDbSchema($dbSchema)
{
$this->dbSchema = $dbSchema;
}
public function setDbUrl($v)
{
$this->dbUrl = $v;
}
public function setDbDriver($v)
{
$this->dbDriver = $v;
}
public function setDbUser($v)
{
$this->dbUser = $v;
}
public function setDbPassword($v)
{
$this->dbPassword = $v;
}
public function setDbEncoding($v)
{
$this->dbEncoding = $v;
}
public function setOutputFile($v)
{
$this->xmlSchema = $v;
}
public function setSamePhpName($v)
{
$this->samePhpName = $v;
}
public function setAddVendorInfo($v)
{
$this->addVendorInfo = (boolean) $v;
}
/**
* Sets set validator bitfield from propel.addValidators property
*
* @param string $v The propel.addValidators property
* @return void
*/
public function setAddValidators($v)
{
// lowercase input
$v = strtolower($v);
// make it a bit expression
$v = str_replace(
array_keys(self::$validatorBitMap), self::$validatorBitMap, $v);
// check if it's a valid boolean expression
if (!preg_match('/[^\d|&~ ]/', $v)) {
// eval the expression
eval("\$v = $v;");
} else {
$this->log("\n\nERROR: NO VALIDATORS ADDED!\n\nThere is an error in propel.addValidators build property.\n\nAllowed tokens are: " . implode(', ', array_keys(self::$validatorBitMap)) . "\n\nAllowed operators are (like in php.ini):\n\n| bitwise OR\n& bitwise AND\n~ bitwise NOT\n\n", PROJECT_MSG_ERR);
$v = self::VALIDATORS_NONE;
}
$this->validatorBits = $v;
}
public function isSamePhpName()
{
return $this->samePhpName;
}
/**
* Default constructor.
* @return void
* @throws BuildException
*/
public function main()
{
$this->log("Propel - CreoleToXMLSchema starting");
$this->log("Your DB settings are:");
$this->log("driver : " . ($this->dbDriver ? $this->dbDriver : "(default)"));
$this->log("URL : " . $this->dbUrl);
//(not yet supported) $this->log("schema : " . $this->dbSchema);
//DocumentTypeImpl docType = new DocumentTypeImpl(null, "database", null,
// "http://jakarta.apache.org/turbine/dtd/database.dtd");
$this->doc = new DOMDocument('1.0', 'utf-8');
$this->doc->formatOutput = true; // pretty printing
$this->doc->appendChild($this->doc->createComment("Autogenerated by CreoleToXMLSchema!"));
try {
$this->generateXML();
$this->log("Writing XML to file: " . $this->xmlSchema);
$outFile = new PhingFile($this->xmlSchema);
$out = new FileWriter($outFile);
$xmlstr = $this->doc->saveXML();
$out->write($xmlstr);
$out->close();
} catch (Exception $e) {
$this->log("There was an error building XML from metadata: " . $e->getMessage(), PROJECT_MSG_ERR);
}
$this->log("Propel - CreoleToXMLSchema finished");
}
/**
* Generates an XML database schema from Creole metadata.
*
* @return void
* @throws Exception a generic exception.
*/
public function generateXML()
{
// Establish db connection
$con = $this->getConnection();
// Get the database Metadata.
$dbInfo = $con->getDatabaseInfo();
// create and add the database node
$databaseNode = $this->createDatabaseNode($dbInfo);
$this->doc->appendChild($databaseNode);
}
/**
* Establishes a Creole database connection
*
* @return object The connection
*/
protected function getConnection() {
// Attemtp to connect to a database.
$this->dsn = Creole::parseDSN($this->dbUrl);
if($this->dbUser) {
$this->dsn["username"] = $this->dbUser;
}
if ($this->dbPassword) {
$this->dsn["password"] = $this->dbPassword;
}
if ($this->dbDriver) {
Creole::registerDriver($this->dsn['phptype'], $this->dbDriver);
}
$con = Creole::getConnection($this->dsn);
$this->log("DB connection established");
return $con;
}
/**
* Creates a database node
*
* @param object $dbInfo The dbInfo for this db
* @return object The database node instance
*/
protected function createDatabaseNode($dbInfo) {
$this->log("Processing database");
$node = $this->doc->createElement("database");
$node->setAttribute("name", $dbInfo->getName());
if ($vendorNode = $this->createVendorInfoNode($dbInfo->getVendorSpecificInfo())) {
$node->appendChild($vendorNode);
}
// create and add table nodes
foreach($dbInfo->getTables() as $table) {
$tableNode = $this->createTableNode($table);
$node->appendChild($tableNode);
}
return $node;
}
/**
* Creates a table node
*
* @param object $table The table
* @return object The table node instance
*/
protected function createTableNode($table) {
$this->log("Processing table: " . $table->toString());
$node = $this->doc->createElement("table");
$node->setAttribute("name", $table->getName());
if ($this->isSamePhpName()) {
$node->setAttribute("phpName", $table->getName());
}
if ($vendorNode = $this->createVendorInfoNode($table->getVendorSpecificInfo())) {
$node->appendChild($vendorNode);
}
// Create and add column nodes, register column validators
$columns = $table->getColumns();
foreach($columns as $column) {
$columnNode = $this->createColumnNode($column);
$node->appendChild($columnNode);
$this->registerValidatorsForColumn($column);
if ($column->isAutoIncrement()) {
$idMethod = 'native';
}
}
if (isset($idMethod)) {
$node->setAttribute("idMethod", $idMethod);
}
// Create and add foreign key nodes.
$foreignKeys = $table->getForeignKeys();
foreach($foreignKeys as $foreignKey) {
$foreignKeyNode = $this->createForeignKeyNode($foreignKey);
$node->appendChild($foreignKeyNode);
}
// Create and add index nodes.
$indices = $table->getIndices();
foreach($indices as $index) {
$indexNode = $this->createIndexNode($index);
$node->appendChild($indexNode);
}
// add an id-method-parameter if we have a sequence that matches table_colname_seq
//
//
$pkey = $table->getPrimaryKey();
if ($pkey) {
$cols = $pkey->getColumns();
if (count($cols) === 1) {
$col = array_shift($cols);
if ($col->isAutoIncrement()) {
$seq_name = $table->getName().'_'.$col->getName().'_seq';
if ($table->getDatabase()->isSequence($seq_name)) {
$idMethodParameterNode = $this->doc->createElement("id-method-parameter");
$idMethodParameterNode->setAttribute("value", $seq_name);
$node->appendChild($idMethodParameterNode);
}
}
}
}
// Create and add validator and rule nodes.
$nodes = array();
$tableName = $table->getName();
if (isset($this->validatorInfos[$tableName])) {
foreach ($this->validatorInfos[$tableName] as $colName => $rules) {
$column = $table->getColumn($colName);
$colName = $column->getName();
foreach ($rules as $rule) {
if (!isset($nodes[$colName])) {
$nodes[$colName] = $this->createValidator($column, $rule['type']);
$node->appendChild($nodes[$colName]);
}
$ruleNode = $this->createRuleNode($column, $rule);
$nodes[$colName]->appendChild($ruleNode);
}
}
}
return $node;
}
/**
* Creates an column node
*
* @param object $column The Creole column
* @return object The column node instance
*/
protected function createColumnNode($column) {
$node = $this->doc->createElement("column");
$table = $column->getTable();
$colName = $column->getName();
$colType = $column->getType();
$colSize = $column->getSize();
$colScale = $column->getScale();
if ($colType === CreoleTypes::OTHER) {
$this->log("Column [" . $table->getName() . "." . $colName . "] has a column type (".$column->getNativeType().") that Propel does not support.", PROJECT_MSG_WARN);
}
$node->setAttribute("name", $colName);
if ($this->isSamePhpName()) {
$node->setAttribute("phpName", $colName);
}
$node->setAttribute("type", PropelTypes::getPropelType($colType));
if ($colSize > 0 && (
$colType == CreoleTypes::CHAR
|| $colType == CreoleTypes::VARCHAR
|| $colType == CreoleTypes::LONGVARCHAR
|| $colType == CreoleTypes::DECIMAL
|| $colType == CreoleTypes::FLOAT
|| $colType == CreoleTypes::NUMERIC)) {
$node->setAttribute("size", (string) $colSize);
}
if ($colScale > 0 && (
$colType == CreoleTypes::DECIMAL
|| $colType == CreoleTypes::FLOAT
|| $colType == CreoleTypes::NUMERIC)) {
$node->setAttribute("scale", (string) $colScale);
}
if (!$column->isNullable()) {
$node->setAttribute("required", "true");
}
if ($column->isAutoIncrement()) {
$node->setAttribute("autoIncrement", "true");
}
if (in_array($colName, $this->getTablePkCols($table))) {
$node->setAttribute("primaryKey", "true");
}
if (($defValue = $column->getDefaultValue()) !== null) {
$node->setAttribute("default", iconv($this->dbEncoding, 'utf-8', $defValue));
}
if ($vendorNode = $this->createVendorInfoNode($column->getVendorSpecificInfo())) {
$node->appendChild($vendorNode);
}
return $node;
}
/**
* Returns the primary key columns for a table
*
* @param object $table The table
* @return array The primary keys
*/
protected function getTablePkCols($table) {
static $columns = array();
$tableName = $table->getName();
if (!isset($columns[$tableName])) {
$columns[$tableName] = array();
$primaryKey = $table->getPrimaryKey();
if ($primaryKey) {
foreach($primaryKey->getColumns() as $colObject) {
$columns[$tableName][] = $colObject->getName();
}
}
}
return $columns[$tableName];
}
/**
* Creates an foreign key node
*
* @param object $foreignKey The foreign key
* @return object The foreign key node instance
*/
protected function createForeignKeyNode($foreignKey) {
$node = $this->doc->createElement("foreign-key");
if ($vendorNode = $this->createVendorInfoNode($foreignKey->getVendorSpecificInfo())) {
$node->appendChild($vendorNode);
}
$refs = $foreignKey->getReferences();
// all references must be to same table, so we can grab table from the first, foreign column
$node->setAttribute("foreignTable", $refs[0][1]->getTable()->getName());
$node->setAttribute("onDelete", $refs[0][2]);
$node->setAttribute("onUpdate", $refs[0][3]);
for($m = 0, $size = count($refs); $m < $size; $m++) {
$refNode = $this->doc->createElement("reference");
$refData = $refs[$m];
$refNode->setAttribute("local", $refData[0]->getName());
$refNode->setAttribute("foreign", $refData[1]->getName());
$node->appendChild($refNode);
}
return $node;
}
/**
* Creates an index node
*
* @param object $index The index
* @return object The index node instance
*/
protected function createIndexNode($index) {
$indexType = $index->isUnique() ? 'unique' : 'index';
$node = $this->doc->createElement($indexType);
$node->setAttribute("name", $index->getName());
$columns = $index->getColumns();
foreach ($columns as $column) {
$tableName = $column->getTable()->getName();
$colName = $column->getName();
$columnNode = $this->doc->createElement("{$indexType}-column");
$columnNode->setAttribute("name", $colName);
$node->appendChild($columnNode);
if ($indexType == 'unique' && $this->isValidatorRequired('unique')) {
$this->validatorInfos[$tableName][$colName][] = array('type' => 'unique');
}
}
if ($vendorNode = $this->createVendorInfoNode($index->getVendorSpecificInfo())) {
$node->appendChild($vendorNode);
}
return $node;
}
/**
* Checks whether to add validators of specified type or not
*
* @param string $type The validator type
* @return boolean
*/
protected function isValidatorRequired($type) {
$type = strtolower($type);
return ($this->validatorBits & self::$validatorBitMap[$type] ? true : false);
}
/**
* Registers column type specific validators if necessary
*
* We'll first collect the validators/rule infos and add them later on to
* have them appended to the table tag as a block.
*
* CreoleTypes are:
*
* BOOLEAN
* BIGINT, SMALLINT, TINYINT, INTEGER
* FLOAT, DOUBLE, NUMERIC, DECIMAL, REAL
* BIGINT, SMALLINT, TINYINT, INTEGER
* TEXT
* BLOB, CLOB, BINARY, VARBINARY, LONGVARBINARY
* DATE, YEAR, TIME
* TIMESTAMP
*
* We will add the following type specific validators:
*
* for notNull columns: required validator
* for unique indexes: unique validator
* for varchar types: maxLength validators (CHAR, VARCHAR, LONGVARCHAR)
* for numeric types: maxValue validators (BIGINT, SMALLINT, TINYINT, INTEGER, FLOAT, DOUBLE, NUMERIC, DECIMAL, REAL)
* for integer and timestamp types: notMatch validator with [^\d]+ (BIGINT, SMALLINT, TINYINT, INTEGER, TIMESTAMP)
* for float types: notMatch validator with [^\d\.]+ (FLOAT, DOUBLE, NUMERIC, DECIMAL, REAL)
*
* @param object $column The Creole column
* @return void
* @todo find out how to evaluate the appropriate size and adjust maxValue rule values appropriate
* @todo find out if float type column values must always notMatch('[^\d\.]+'), i.e. digits and point for any db vendor, language etc.
*/
protected function registerValidatorsForColumn($column) {
$table = $column->getTable();
$tableName = $table->getName();
$colName = $column->getName();
$colType = $column->getType();
$colSize = $column->getSize();
if ($this->isValidatorRequired('required')) {
$ruleInfo = array('type' => 'required');
$this->validatorInfos[$tableName][$colName][] = $ruleInfo;
}
$isPrimarykeyCol = in_array($colName, $this->getTablePkCols($table));
if ($this->isValidatorRequired('unique') && $isPrimarykeyCol) {
$ruleInfo = array('type' => 'unique');
$this->validatorInfos[$tableName][$colName][] = $ruleInfo;
}
if ($this->isValidatorRequired('maxLength') &&
$colSize > 0 && in_array($colType, array(
CreoleTypes::CHAR,
CreoleTypes::VARCHAR,
CreoleTypes::LONGVARCHAR))) {
$ruleInfo = array('type' => 'maxLength', 'value' => $colSize);
$this->validatorInfos[$tableName][$colName][] = $ruleInfo;
}
if ($this->isValidatorRequired('maxValue') &&
$colSize > 0 && in_array($colType, array(
CreoleTypes::SMALLINT,
CreoleTypes::TINYINT,
CreoleTypes::INTEGER,
CreoleTypes::BIGINT,
CreoleTypes::FLOAT,
CreoleTypes::DOUBLE,
CreoleTypes::NUMERIC,
CreoleTypes::DECIMAL,
CreoleTypes::REAL))) {
// TODO: how to evaluate the appropriate size??
$this->log("WARNING: maxValue validator added for column $colName. You will have to adjust the size value manually.", PROJECT_MSG_WARN);
$ruleInfo = array('type' => 'maxValue', 'value' => $colSize);
$this->validatorInfos[$tableName][$colName][] = $ruleInfo;
}
if ($this->isValidatorRequired('type') &&
$colSize > 0 && in_array($colType, array(
CreoleTypes::SMALLINT,
CreoleTypes::TINYINT,
CreoleTypes::INTEGER,
CreoleTypes::TIMESTAMP))) {
$ruleInfo = array('type' => 'type', 'value' => '[^\d]+');
$this->validatorInfos[$tableName][$colName][] = $ruleInfo;
}
if ($this->isValidatorRequired('type') &&
$colSize > 0 && in_array($colType, array(
CreoleTypes::FLOAT,
CreoleTypes::DOUBLE,
CreoleTypes::NUMERIC,
CreoleTypes::DECIMAL,
CreoleTypes::REAL))) {
// TODO: is this always true??
$ruleInfo = array('type' => 'type', 'value' => '[^\d\.]+');
$this->validatorInfos[$tableName][$colName][] = $ruleInfo;
}
}
/**
* Creates a validator node
*
* @param object $column The Creole column
* @param integer $type The validator type
* @return object The validator node instance
*/
protected function createValidator($column, $type) {
$node = $this->doc->createElement('validator');
$node->setAttribute('column', $column->getName());
return $node;
}
/**
* Creates a rule node
*
* @param object $column The Creole column
* @param array $rule The rule info
* @return object The rule node instance
*/
protected function createRuleNode($column, $rule) {
extract($rule);
// create message
$colName = $column->getName();
$tableName = $column->getTable()->getName();
$msg = self::$validatorMessages[strtolower($rule)];
array_unshift($tmp = compact($msg['var']), $msg['msg']);
$msg = call_user_func_array('sprintf', $tmp);
// add node
$node = $this->doc->createElement('rule');
$node->setAttribute('name', $rule == 'type' ? 'notMatch' : $rule);
$node->setAttribute('message', $msg);
return $node;
}
/**
* Creates a vendor info node
*
* returns false if no vendor info can or has to be added
*
* @param array $vendorInfo The validator info
* @return object|boolean The vendor info instance or false
*/
protected function createVendorInfoNode($vendorInfo)
{
if(!$vendorInfo OR !$this->addVendorInfo) {
return false;
}
$vendorNode = $this->doc->createElement("vendor");
$vendorNode->setAttribute("type", $this->dsn["phptype"]);
foreach($vendorInfo as $key => $value) {
$parameterNode = $this->doc->createElement("parameter");
$value = iconv($this->dbEncoding, "utf-8", $value);
$parameterNode->setAttribute("name", $key);
$parameterNode->setAttribute("value", $value);
$vendorNode->appendChild($parameterNode);
}
return $vendorNode;
}
}

View File

@ -0,0 +1,80 @@
<?php
/*
* $Id: PropelDataDTDTask.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/phing/AbstractPropelDataModelTask.php';
include_once 'propel/engine/builder/om/ClassTools.php';
/**
* This Task creates the OM classes based on the XML schema file.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.phing
*/
class PropelDataDTDTask extends AbstractPropelDataModelTask {
public function main() {
// check to make sure task received all correct params
$this->validate();
if(!$this->mapperElement) {
throw new BuildException("You must use a <mapper/> element to describe how names should be transformed.");
}
$basepath = $this->getOutputDirectory();
// Get new Capsule context
$generator = $this->createContext();
$generator->put("basepath", $basepath); // make available to other templates
// we need some values that were loaded into the template context
$basePrefix = $generator->get('basePrefix');
$project = $generator->get('project');
foreach ($this->getDataModels() as $dataModel) {
$this->log("Processing Datamodel : " . $dataModel->getName());
foreach ($dataModel->getDatabases() as $database) {
$outFile = $this->getMappedFile($dataModel->getName());
$generator->put("tables", $database->getTables());
$generator->parse("data/dtd/dataset.tpl", $outFile->getAbsolutePath());
$this->log("Generating DTD for database: " . $database->getName());
$this->log("Creating DTD file: " . $outFile->getPath());
foreach ($database->getTables() as $tbl) {
$this->log("\t + " . $tbl->getName());
$generator->put("table", $tbl);
$generator->parse("data/dtd/table.tpl", $outFile->getAbsolutePath(), true);
}
} // foreach database
} // foreach dataModel
} // main()
}

View File

@ -0,0 +1,383 @@
<?php
/*
* $Id: PropelDataDumpTask.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
include_once 'creole/Creole.php';
/**
* Dumps the contenst of selected databases to XML data dump file.
*
* The generated XML files can have corresponding DTD files generated using the
* PropelDataDTDTask. The results of the data dump can be converted to SQL using
* the PropelDataSQLTask class.
*
* The database may be specified (via 'databaseName' attribute) if you only want to dump
* the contents of one database. Otherwise it is assumed that all databases described
* by datamodel schema file(s) will be dumped.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Fedor Karpelevitch <fedor.karpelevitch@home.com> (Torque)
* @author Jason van Zyl <jvanzyl@zenplex.com> (Torque)
* @author Daniel Rall <dlr@finemaltcoding.com> (Torque)
* @version $Revision: 536 $
* @package propel.phing
*/
class PropelDataDumpTask extends AbstractPropelDataModelTask {
/**
* Database name.
* The database name may be optionally specified in the XML if you only want
* to dump the contents of one database.
*/
private $databaseName;
/**
* Database URL used for Creole connection.
* This is a PEAR-compatible (loosely) DSN URL.
*/
private $databaseUrl;
/**
* Database driver used for Creole connection.
* This should normally be left blank so that default (Creole built-in) driver for database type is used.
*/
private $databaseDriver;
/**
* Database user used for Creole connection.
* @deprecated Put username in databaseUrl.
*/
private $databaseUser;
/**
* Database password used for Creole connection.
* @deprecated Put password in databaseUrl.
*/
private $databasePassword;
/**
* Properties file that maps a data XML file to a particular database.
* @var PhingFile
*/
private $datadbmap;
/**
* The database connection used to retrieve the data to dump.
* Needs to be public so that the TableInfo class can access it.
*/
public $conn;
/**
* The statement used to acquire the data to dump.
*/
private $stmt;
/**
* Set the file that maps between data XML files and databases.
*
* @param PhingFile $sqldbmap the db map
* @return void
*/
public function setDataDbMap(PhingFile $datadbmap)
{
$this->datadbmap = $datadbmap;
}
/**
* Get the file that maps between data XML files and databases.
*
* @return PhingFile $datadbmap.
*/
public function getDataDbMap()
{
return $this->datadbmap;
}
/**
* Get the database name to dump
*
* @return The DatabaseName value
*/
public function getDatabaseName()
{
return $this->databaseName;
}
/**
* Set the database name
*
* @param v The new DatabaseName value
*/
public function setDatabaseName($v)
{
$this->databaseName = $v;
}
/**
* Get the database url
*
* @return The DatabaseUrl value
*/
public function getDatabaseUrl()
{
return $this->databaseUrl;
}
/**
* Set the database url
*
* @param string $v The PEAR-compatible database DSN URL.
*/
public function setDatabaseUrl($v)
{
$this->databaseUrl = $v;
}
/**
* Get the database user
*
* @return string database user
* @deprecated
*/
public function getDatabaseUser()
{
return $this->databaseUser;
}
/**
* Set the database user
*
* @param string $v The new DatabaseUser value
* @deprecated Specify user in DSN URL.
*/
public function setDatabaseUser($v)
{
$this->databaseUser = $v;
}
/**
* Get the database password
*
* @return string database password
*/
public function getDatabasePassword()
{
return $this->databasePassword;
}
/**
* Set the database password
*
* @param string $v The new DatabasePassword value
* @deprecated Specify database password in DSN URL.
*/
public function setDatabasePassword($v)
{
$this->databasePassword = $v;
}
/**
* Get the database driver name
*
* @return string database driver name
*/
public function getDatabaseDriver()
{
return $this->databaseDriver;
}
/**
* Set the database driver name
*
* @param string $v The new DatabaseDriver value
*/
public function setDatabaseDriver($v)
{
$this->databaseDriver = $v;
}
/**
* Create the data XML -> database map.
*
* This is necessary because there is currently no other method of knowing which
* data XML files correspond to which database. This map allows us to convert multiple
* data XML files into SQL.
*
* @throws IOException - if unable to store properties
*/
private function createDataDbMap()
{
if ($this->getDataDbMap() === null) {
return;
}
// Produce the sql -> database map
$datadbmap = new Properties();
// Check to see if the sqldbmap has already been created.
if ($this->getDataDbMap()->exists()) {
$datadbmap->load($this->getDataDbMap());
}
foreach ($this->getDataModels() as $dataModel) { // there is really one 1 db per datamodel
foreach ($dataModel->getDatabases() as $database) {
// if database name is specified, then we only want to dump that one db.
if (empty($this->databaseName) || ($this->databaseName && $database->getName() == $this->databaseName)) {
$outFile = $this->getMappedFile($dataModel->getName());
$datadbmap->setProperty($outFile->getName(), $database->getName());
}
}
}
try {
$datadbmap->store($this->getDataDbMap(), "Data XML file -> Database map");
} catch (IOException $e) {
throw new IOException("Unable to store properties: ". $e->getMessage());
}
}
/**
* Iterates through each datamodel/database, dumps the contents of all tables and creates a DOM XML doc.
*
* @return void
* @throws BuildException
*/
public function main()
{
$this->validate();
$buf = "Database settings:\n"
. " driver: " . ($this->databaseDriver ? $this->databaseDriver : "(default)" ). "\n"
. " URL: " . $this->databaseUrl . "\n"
. ($this->databaseUser ? " user: " . $this->databaseUser . "\n" : "") // deprecated
. ($this->databasePassword ? " password: " . $this->databasePassword . "\n" : ""); // deprecated
$this->log($buf, PROJECT_MSG_VERBOSE);
// 1) First create the Data XML -> database name map.
$this->createDataDbMap();
// 2) Now go create the XML files from teh database(s)
foreach ($this->getDataModels() as $dataModel) { // there is really one 1 db per datamodel
foreach ($dataModel->getDatabases() as $database) {
// if database name is specified, then we only want to dump that one db.
if (empty($this->databaseName) || ($this->databaseName && $database->getName() == $this->databaseName)) {
$outFile = $this->getMappedFile($dataModel->getName());
$this->log("Dumping data to XML for database: " . $database->getName());
$this->log("Writing to XML file: " . $outFile->getName());
try {
$url = str_replace("@DB@", $database->getName(), $this->databaseUrl);
$buf = "Database settings:\n"
. " driver: " . ($this->databaseDriver ? $this->databaseDriver : "(default)" ). "\n"
. " URL: " . $url . "\n"
. ($this->databaseUser ? " user: " . $this->databaseUser . "\n" : "")
. ($this->databasePassword ? " password: " . $this->databasePassword . "\n" : "");
$this->log($buf, PROJECT_MSG_VERBOSE);
$dsn = Creole::parseDSN($url);
// deprecated, but here for BC
if ($this->databaseUser) {
$dsn['username'] = $this->databaseUser;
}
if ($this->databasePassword) {
$dsn['password'] = $this->databasePassword;
}
if ($this->databaseName) {
$dsn['database'] = $this->databaseName;
}
if ($this->databaseDriver) {
Creole::registerDriver($dsn['phptype'], $this->databaseDriver);
}
$this->conn = Creole::getConnection($dsn);
$doc = $this->createXMLDoc($database);
$doc->save($outFile->getAbsolutePath());
} catch (SQLException $se) {
$this->log("SQLException while connecting to DB: ". $se->getMessage(), PROJECT_MSG_ERR);
throw new BuildException($se);
}
} // if databaseName && database->getName == databaseName
} // foreach database
} // foreach datamodel
}
/**
* Gets ResultSet of query to fetch all data from a table.
* @param string $tableName
* @return ResultSet
*/
private function getTableDataRS($tableName) {
// Set Statement object in associated PropelDataDump
// instance.
return $this->conn->createStatement()->executeQuery("SELECT * FROM " . $this->getPlatformForTargetDatabase()->quoteIdentifier ( $tableName ) );
}
/**
* Creates a DOM document containing data for specified database.
* @param Database $database
* @return DOMDocument
*/
private function createXMLDoc(Database $database) {
$doc = new DOMDocument('1.0', 'utf-8');
$doc->formatOutput = true; // pretty printing
$doc->appendChild($doc->createComment("Created by data/dump/Control.tpl template."));
$dsNode = $doc->createElement("dataset");
$dsNode->setAttribute("name", "all");
$doc->appendChild($dsNode);
$this->log("Building DOM tree containing data from tables:");
foreach ($database->getTables() as $tbl) {
$this->log("\t+ " . $tbl->getName());
$rs = $this->getTableDataRS($tbl->getName());
while ($rs->next()) {
$rowNode = $doc->createElement($tbl->getPhpName());
foreach ($tbl->getColumns() as $col) {
$cval = $rs->get($col->getName());
if ($cval !== null) {
$rowNode->setAttribute($col->getPhpName(), iconv($this->dbEncoding, 'utf-8', $cval));
}
}
$dsNode->appendChild($rowNode);
unset($rowNode);
}
$rs->close();
}
return $doc;
}
}

View File

@ -0,0 +1,131 @@
<?php
/*
* $Id: PropelDataModelTask.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/phing/AbstractPropelDataModelTask.php';
include_once 'propel/engine/database/model/AppData.php';
include_once 'propel/engine/database/model/Database.php';
include_once 'propel/engine/database/transform/XmlToAppData.php';
/**
* A generic class that simply loads the data model and parses a control template.
*
* This class exists largely for compatibility with early Propel where this was
* a CapsuleTask subclass. This class also makes it easy to quickly add some custom
* datamodel-based transformations (by allowing you to put the logic in the templates).
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.phing
* @version $Revision: 536 $
*/
class PropelDataModelTask extends AbstractPropelDataModelTask {
/**
* This is the file where the generated text
* will be placed.
* @var string
*/
protected $outputFile;
/**
* This is the control template that governs the output.
* It may or may not invoke the services of worker
* templates.
* @var string
*/
protected $controlTemplate;
/**
* [REQUIRED] Set the output file for the
* generation process.
* @param string $outputFile (TODO: change this to File)
* @return void
*/
public function setOutputFile($outputFile) {
$this->outputFile = $outputFile;
}
/**
* Get the output file for the
* generation process.
* @return string
*/
public function getOutputFile() {
return $this->outputFile;
}
/**
* [REQUIRED] Set the control template for the
* generating process.
* @param string $controlTemplate
* @return void
*/
public function setControlTemplate ($controlTemplate) {
$this->controlTemplate = $controlTemplate;
}
/**
* Get the control template for the
* generating process.
* @return string
*/
public function getControlTemplate() {
return $this->controlTemplate;
}
protected function validate()
{
parent::validate();
// Make sure the control template is set.
if ($this->controlTemplate === null) {
throw new BuildException("The control template needs to be defined!");
}
// Make sure there is an output file.
if ($this->outputFile === null) {
throw new BuildException("The output file needs to be defined!");
}
}
/**
* Creates Capsule context and parses control template.
* @return void
*/
public function main()
{
$this->validate();
$context = $this->createContext();
$context->put("dataModels", $this->getDataModels());
$path = $this->outputDirectory . DIRECTORY_SEPARATOR . $this->outputFile;
$this->log("Generating to file " . $path);
try {
$this->log("Parsing control template: " . $this->controlTemplate);
$context->parse($this->controlTemplate, $path);
} catch (Exception $ioe) {
throw new BuildException("Cannot write parsed template: ". $ioe->getMessage());
}
}
}

View File

@ -0,0 +1,219 @@
<?php
/*
* $Id: PropelDataSQLTask.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
include_once 'propel/engine/database/model/AppData.php';
include_once 'propel/engine/database/model/Database.php';
include_once 'propel/engine/database/transform/XmlToAppData.php';
include_once 'propel/engine/database/transform/XmlToData.php';
/**
* Task that transforms XML datadump files into files containing SQL INSERT statements.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Jason van Zyl <jvanzyl@periapt.com> (Torque)
* @author John McNally <jmcnally@collab.net> (Torque)
* @author Fedor Karpelevitch <fedor.karpelevitch@home.com> (Torque)
* @version $Revision: 536 $
* @package propel.phing
*/
class PropelDataSQLTask extends AbstractPropelDataModelTask {
/**
* Properties file that maps an SQL file to a particular database.
* @var PhingFile
*/
private $sqldbmap;
/**
* Properties file that maps a data XML file to a particular database.
* @var PhingFile
*/
private $datadbmap;
/**
* The base directory in which to find data XML files.
* @var PhingFile
*/
private $srcDir;
/**
* Set the file that maps between SQL files and databases.
*
* @param PhingFile $sqldbmap the sql -> db map.
* @return void
*/
public function setSqlDbMap(PhingFile $sqldbmap)
{
$this->sqldbmap = $sqldbmap;
}
/**
* Get the file that maps between SQL files and databases.
*
* @return PhingFile sqldbmap.
*/
public function getSqlDbMap()
{
return $this->sqldbmap;
}
/**
* Set the file that maps between data XML files and databases.
*
* @param PhingFile $sqldbmap the db map
* @return void
*/
public function setDataDbMap(PhingFile $datadbmap)
{
$this->datadbmap = $datadbmap;
}
/**
* Get the file that maps between data XML files and databases.
*
* @return PhingFile $datadbmap.
*/
public function getDataDbMap()
{
return $this->datadbmap;
}
/**
* Set the src directory for the data xml files listed in the datadbmap file.
* @param PhingFile $srcDir data xml source directory
*/
public function setSrcDir(PhingFile $srcDir)
{
$this->srcDir = $srcDir;
}
/**
* Get the src directory for the data xml files listed in the datadbmap file.
*
* @return PhingFile data xml source directory
*/
public function getSrcDir()
{
return $this->srcDir;
}
/**
* Search through all data models looking for matching database.
* @return Database or NULL if none found.
*/
private function getDatabase($name)
{
foreach($this->getDataModels() as $dm) {
foreach($dm->getDatabases() as $db) {
if ($db->getName() == $name) {
return $db;
}
}
}
}
/**
* Main method parses the XML files and creates SQL files.
*
* @return void
* @throws Exception If there is an error parsing the data xml.
*/
public function main()
{
$this->validate();
$targetDatabase = $this->getTargetDatabase();
$platform = $this->getPlatformForTargetDatabase();
// Load the Data XML -> DB Name properties
$map = new Properties();
try {
$map->load($this->getDataDbMap());
} catch (IOException $ioe) {
throw new BuildException("Cannot open and process the datadbmap!", $ioe);
}
DataModelBuilder::setBuildProperties($this->getPropelProperties());
// Parse each file in teh data -> db map
foreach($map->keys() as $dataXMLFilename) {
$dataXMLFile = new PhingFile($this->srcDir, $dataXMLFilename);
// if file exists then proceed
if ($dataXMLFile->exists()) {
$dbname = $map->get($dataXMLFilename);
$db = $this->getDatabase($dbname);
if (!$db) {
throw new BuildException("Cannot find instantiated Database for name '$dbname' from datadbmap file.");
}
$db->setPlatform($platform);
$outFile = $this->getMappedFile($dataXMLFilename);
$this->log("Creating SQL from XML data dump file: " . $dataXMLFile->getAbsolutePath());
try {
$dataXmlParser = new XmlToData($db, $this->dbEncoding);
$data = $dataXmlParser->parseFile($dataXMLFile->getAbsolutePath());
} catch (Exception $e) {
throw new Exception("Exception parsing data XML: " . $e->getMessage());
}
$fp = fopen($outFile->getAbsolutePath(), 'w');
$currTable = null;
foreach ($data as $dataRow) {
if ($currTable !== $dataRow->getTable()) {
$currTable = $dataRow->getTable();
$builder = DataModelBuilder::builderFactory($currTable, 'datasql');
}
$sql = $builder->buildRowSql($dataRow);
fwrite($fp, $sql);
}
fclose($fp);
// Place the generated SQL file(s)
$p = new Properties();
if ($this->getSqlDbMap()->exists()) {
$p->load($this->getSqlDbMap());
}
$p->setProperty($outFile->getName(), $db->getName());
$p->store($this->getSqlDbMap(), "Sqlfile -> Database map");
} else {
$this->log("File '" . $dataXMLFile->getAbsolutePath()
. "' in datadbmap does not exist, so skipping it.", PROJECT_MSG_WARN);
}
} // foreach data xml file
} // main()
}

View File

@ -0,0 +1,177 @@
<?php
/*
* $Id: PropelGraphvizTask.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
include_once 'propel/engine/database/model/AppData.php';
//require_once 'phing/Task.php';
/**
* A task to generate Graphviz png images from propel datamodel.
*
* @author Mark Kimsal
* @version $Revision: 536 $
* @package propel.phing
*/
class PropelGraphvizTask extends AbstractPropelDataModelTask {
/**
* The properties file that maps an SQL file to a particular database.
* @var PhingFile
*/
private $sqldbmap;
/**
* Name of the database.
*/
private $database;
/**
* Name of the output directory.
*/
private $outDir;
/**
* Set the sqldbmap.
* @param PhingFile $sqldbmap The db map.
*/
public function setOutputDirectory(PhingFile $out)
{
if (!$out->exists()) {
$out->mkdirs();
}
$this->outDir = $out;
}
/**
* Set the sqldbmap.
* @param PhingFile $sqldbmap The db map.
*/
public function setSqlDbMap(PhingFile $sqldbmap)
{
$this->sqldbmap = $sqldbmap;
}
/**
* Get the sqldbmap.
* @return PhingFile $sqldbmap.
*/
public function getSqlDbMap()
{
return $this->sqldbmap;
}
/**
* Set the database name.
* @param string $database
*/
public function setDatabase($database)
{
$this->database = $database;
}
/**
* Get the database name.
* @return string
*/
public function getDatabase()
{
return $this->database;
}
public function main()
{
$count = 0;
$dotSyntax = '';
// file we are going to create
$dbMaps = $this->getDataModelDbMap();
foreach ($this->getDataModels() as $dataModel) {
$dotSyntax .= "digraph G {\n";
foreach ($dataModel->getDatabases() as $database) {
$this->log("db: " . $database->getName());
//print the tables
foreach($database->getTables() as $tbl) {
$this->log("\t+ " . $tbl->getName());
++$count;
$dotSyntax .= 'node'.$tbl->getName().' [label="{<table>'.$tbl->getName().'|<cols>';
foreach ($tbl->getColumns() as $col) {
$dotSyntax .= $col->getName() . ' (' . $col->getType() . ')';
if ($col->getForeignKey() != null ) {
$dotSyntax .= ' [FK]';
} elseif ($col->isPrimaryKey()) {
$dotSyntax .= ' [PK]';
}
$dotSyntax .= '\l';
}
$dotSyntax .= '}", shape=record];';
$dotSyntax .= "\n";
}
//print the relations
$count = 0;
$dotSyntax .= "\n";
foreach($database->getTables() as $tbl) {
++$count;
foreach ($tbl->getColumns() as $col) {
$fk = $col->getForeignKey();
if ( $fk == null ) continue;
$dotSyntax .= 'node'.$tbl->getName() .':cols -> node'.$fk->getForeignTableName() . ':table [label="' . $col->getName() . '=' . implode(',', $fk->getForeignColumns()) . ' "];';
$dotSyntax .= "\n";
}
}
} // foreach database
$dotSyntax .= "}\n";
$this->writeDot($dotSyntax,$this->outDir);
} //foreach datamodels
} // main()
/**
* probably insecure
*/
function writeDot($dotSyntax, PhingFile $outputDir) {
$file = new PhingFile($outputDir, 'schema.dot');
$this->log("Writing dot file to " . $file->getAbsolutePath());
file_put_contents($file->getAbsolutePath(), $dotSyntax);
}
}

View File

@ -0,0 +1,212 @@
<?php
/*
* $Id: PropelOMTask.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/phing/AbstractPropelDataModelTask.php';
include_once 'propel/engine/builder/om/ClassTools.php';
require_once 'propel/engine/builder/om/OMBuilder.php';
/**
* This Task creates the OM classes based on the XML schema file.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.phing
*/
class PropelOMTask extends AbstractPropelDataModelTask {
/**
* The platform (php4, php5, etc.) for which the om is being built.
* @var string
*/
private $targetPlatform;
/**
* Sets the platform (php4, php5, etc.) for which the om is being built.
* @param string $v
*/
public function setTargetPlatform($v) {
$this->targetPlatform = $v;
}
/**
* Gets the platform (php4, php5, etc.) for which the om is being built.
* @return string
*/
public function getTargetPlatform() {
return $this->targetPlatform;
}
/**
* Utility method to create directory for package if it doesn't already exist.
* @param string $path The [relative] package path.
* @throws BuildException - if there is an error creating directories
*/
protected function ensureDirExists($path)
{
$f = new PhingFile($this->getOutputDirectory(), $path);
if (!$f->exists()) {
if (!$f->mkdirs()) {
throw new BuildException("Error creating directories: ". $f->getPath());
}
}
}
/**
* Uses a builder class to create the output class.
* This method assumes that the DataModelBuilder class has been initialized with the build properties.
* @param OMBuilder $builder
* @param boolean $overwrite Whether to overwrite existing files with te new ones (default is YES).
* @todo -cPropelOMTask Consider refactoring build() method into AbstractPropelDataModelTask (would need to be more generic).
*/
protected function build(OMBuilder $builder, $overwrite = true)
{
$path = $builder->getClassFilePath();
$this->ensureDirExists(dirname($path));
$_f = new PhingFile($this->getOutputDirectory(), $path);
if ($overwrite || !$_f->exists()) {
$this->log("\t\t-> " . $builder->getClassname() . " [builder: " . get_class($builder) . "]");
$script = $builder->build();
file_put_contents($_f->getAbsolutePath(), $script);
foreach($builder->getWarnings() as $warning) {
$this->log($warning, PROJECT_MSG_WARN);
}
} else {
$this->log("\t\t-> (exists) " . $builder->getClassname());
}
}
/**
* Main method builds all the targets for a typical propel project.
*/
public function main()
{
// check to make sure task received all correct params
$this->validate();
$basepath = $this->getOutputDirectory();
// Get new Capsule context
$generator = $this->createContext();
$generator->put("basepath", $basepath); // make available to other templates
$targetPlatform = $this->getTargetPlatform(); // convenience for embedding in strings below
// we need some values that were loaded into the template context
$basePrefix = $generator->get('basePrefix');
$project = $generator->get('project');
DataModelBuilder::setBuildProperties($this->getPropelProperties());
foreach ($this->getDataModels() as $dataModel) {
$this->log("Processing Datamodel : " . $dataModel->getName());
foreach ($dataModel->getDatabases() as $database) {
$this->log(" - processing database : " . $database->getName());
$generator->put("platform", $database->getPlatform());
foreach ($database->getTables() as $table) {
if (!$table->isForReferenceOnly()) {
$this->log("\t+ " . $table->getName());
// -----------------------------------------------------------------------------------------
// Create Peer, Object, and MapBuilder classes
// -----------------------------------------------------------------------------------------
// these files are always created / overwrite any existing files
foreach(array('peer', 'object', 'mapbuilder') as $target) {
$builder = DataModelBuilder::builderFactory($table, $target);
$this->build($builder);
}
// -----------------------------------------------------------------------------------------
// Create [empty] stub Peer and Object classes if they don't exist
// -----------------------------------------------------------------------------------------
// these classes are only generated if they don't already exist
foreach(array('peerstub', 'objectstub') as $target) {
$builder = DataModelBuilder::builderFactory($table, $target);
$this->build($builder, $overwrite=false);
}
// -----------------------------------------------------------------------------------------
// Create [empty] stub child Object classes if they don't exist
// -----------------------------------------------------------------------------------------
// If table has enumerated children (uses inheritance) then create the empty child stub classes if they don't already exist.
if ($table->getChildrenColumn()) {
$col = $table->getChildrenColumn();
if ($col->isEnumeratedClasses()) {
foreach ($col->getChildren() as $child) {
$builder = DataModelBuilder::builderFactory($table, 'objectmultiextend');
$builder->setChild($child);
$this->build($builder, $overwrite=false);
} // foreach
} // if col->is enumerated
} // if tbl->getChildrenCol
// -----------------------------------------------------------------------------------------
// Create [empty] Interface if it doesn't exist
// -----------------------------------------------------------------------------------------
// Create [empty] interface if it does not already exist
if ($table->getInterface()) {
$builder = DataModelBuilder::builderFactory($table, 'interface');
$this->build($builder, $overwrite=false);
}
// -----------------------------------------------------------------------------------------
// Create tree Node classes
// -----------------------------------------------------------------------------------------
if ($table->isTree()) {
foreach(array('nodepeer', 'node') as $target) {
$builder = DataModelBuilder::builderFactory($table, $target);
$this->build($builder);
}
foreach(array('nodepeerstub', 'nodestub') as $target) {
$builder = DataModelBuilder::builderFactory($table, $target);
$this->build($builder, $overwrite=false);
}
} // if Table->isTree()
} // if !$table->isForReferenceOnly()
} // foreach table
} // foreach database
} // foreach dataModel
} // main()
}

View File

@ -0,0 +1,236 @@
<?php
/*
* $Id: PropelOldOMTask.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'propel/phing/AbstractPropelDataModelTask.php';
include_once 'propel/engine/builder/om/ClassTools.php';
/**
* This Task creates the OM classes based on the XML schema file using the legacy templates.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.phing
* @deprecated
*/
class PropelOldOMTask extends AbstractPropelDataModelTask {
/**
* The platform (php4, php5, etc.) for which the om is being built.
* @var string
*/
private $targetPlatform;
/**
* Sets the platform (php4, php5, etc.) for which the om is being built.
* @param string $v
*/
public function setTargetPlatform($v) {
$this->targetPlatform = $v;
}
/**
* Gets the platform (php4, php5, etc.) for which the om is being built.
* @return string
*/
public function getTargetPlatform() {
return $this->targetPlatform;
}
public function main() {
// check to make sure task received all correct params
$this->validate();
$basepath = $this->getOutputDirectory();
// Get new Capsule context
$generator = $this->createContext();
$generator->put("basepath", $basepath); // make available to other templates
$targetPlatform = $this->getTargetPlatform(); // convenience for embedding in strings below
// we need some values that were loaded into the template context
$basePrefix = $generator->get('basePrefix');
$project = $generator->get('project');
foreach ($this->getDataModels() as $dataModel) {
$this->log("Processing Datamodel : " . $dataModel->getName());
foreach ($dataModel->getDatabases() as $database) {
$this->log(" - processing database : " . $database->getName());
$generator->put("platform", $database->getPlatform());
foreach ($database->getTables() as $table) {
if (!$table->isForReferenceOnly()) {
if ($table->getPackage()) {
$package = $table->getPackage();
} else {
$package = $this->targetPackage;
}
$pkbase = "$package.om";
$pkpeer = "$package";
$pkmap = "$package.map";
// make these available
$generator->put("package", $package);
$generator->put("pkbase", $pkbase);
//$generator->put("pkpeer", $pkpeer); -- we're not using this yet
$generator->put("pkmap", $pkmap);
foreach(array($pkpeer, $pkmap, $pkbase) as $pk) {
$path = strtr($pk, '.', '/');
$f = new PhingFile($this->getOutputDirectory(), $path);
if (!$f->exists()) {
if (!$f->mkdirs()) {
throw new Exception("Error creating directories: ". $f->getPath());
}
}
} // for each package
$this->log("\t+ " . $table->getName());
$generator->put("table", $table);
// Create the Base Peer class
$this->log("\t\t-> " . $basePrefix . $table->getPhpName() . "Peer");
$path = ClassTools::getFilePath($pkbase, $basePrefix . $table->getPhpName() . "Peer");
$generator->parse("om/$targetPlatform/Peer.tpl", $path);
// Create the Base object class
$this->log("\t\t-> " . $basePrefix . $table->getPhpName());
$path = ClassTools::getFilePath($pkbase, $basePrefix . $table->getPhpName());
$generator->parse("om/$targetPlatform/Object.tpl", $path);
if ($table->isTree()) {
// Create the Base NodePeer class
$this->log("\t\t-> " . $basePrefix . $table->getPhpName() . "NodePeer");
$path = ClassTools::getFilePath($pkbase, $basePrefix . $table->getPhpName() . "NodePeer");
$generator->parse("om/$targetPlatform/NodePeer.tpl", $path);
// Create the Base Node class if the table is a tree
$this->log("\t\t-> " . $basePrefix . $table->getPhpName() . "Node");
$path = ClassTools::getFilePath($pkbase, $basePrefix . $table->getPhpName() . "Node");
$generator->parse("om/$targetPlatform/Node.tpl", $path);
}
// Create MapBuilder class if this table is not an alias
if (!$table->isAlias()) {
$this->log("\t\t-> " . $table->getPhpName() . "MapBuilder");
$path = ClassTools::getFilePath($pkmap, $table->getPhpName() . "MapBuilder");
$generator->parse("om/$targetPlatform/MapBuilder.tpl", $path);
} // if !$table->isAlias()
// Create [empty] stub Peer class if it does not already exist
$path = ClassTools::getFilePath($package, $table->getPhpName() . "Peer");
$_f = new PhingFile($basepath, $path);
if (!$_f->exists()) {
$this->log("\t\t-> " . $table->getPhpName() . "Peer");
$generator->parse("om/$targetPlatform/ExtensionPeer.tpl", $path);
} else {
$this->log("\t\t-> (exists) " . $table->getPhpName() . "Peer");
}
// Create [empty] stub object class if it does not already exist
$path = ClassTools::getFilePath($package, $table->getPhpName());
$_f = new PhingFile($basepath, $path);
if (!$_f->exists()) {
$this->log("\t\t-> " . $table->getPhpName());
$generator->parse("om/$targetPlatform/ExtensionObject.tpl", $path);
} else {
$this->log("\t\t-> (exists) " . $table->getPhpName());
}
if ($table->isTree()) {
// Create [empty] stub Node Peer class if it does not already exist
$path = ClassTools::getFilePath($package, $table->getPhpName() . "NodePeer");
$_f = new PhingFile($basepath, $path);
if (!$_f->exists()) {
$this->log("\t\t-> " . $table->getPhpName() . "NodePeer");
$generator->parse("om/$targetPlatform/ExtensionNodePeer.tpl", $path);
} else {
$this->log("\t\t-> (exists) " . $table->getPhpName() . "NodePeer");
}
// Create [empty] stub Node class if it does not already exist
$path = ClassTools::getFilePath($package, $table->getPhpName() . "Node");
$_f = new PhingFile($basepath, $path);
if (!$_f->exists()) {
$this->log("\t\t-> " . $table->getPhpName() . "Node");
$generator->parse("om/$targetPlatform/ExtensionNode.tpl", $path);
} else {
$this->log("\t\t-> (exists) " . $table->getPhpName() . "Node");
}
}
// Create [empty] interface if it does not already exist
if ($table->getInterface()) {
$path = ClassTools::getFilePath($table->getInterface());
$_f = new PhingFile($basepath, $path);
if (!$_f->exists()) {
$_dir = new PhingFile(dirname($_f->getAbsolutePath()));
$_dir->mkdirs();
$this->log("\t\t-> " . $table->getInterface());
$generator->parse("om/$targetPlatform/Interface.tpl", $path);
} else {
$this->log("\t\t-> (exists) " . $table->getInterface());
}
}
// If table has enumerated children (uses inheritance) then create the empty child stub classes
// if they don't already exist.
if ($table->getChildrenColumn()) {
$col = $table->getChildrenColumn();
if ($col->isEnumeratedClasses()) {
foreach ($col->getChildren() as $child) {
$childpkg = ($child->getPackage() ? $child->getPackage() : $package);
$generator->put("child", $child);
$generator->put("package", $childpkg);
$path = ClassTools::getFilePath($childpkg, $child->getClassName());
$_f = new PhingFile($basepath, $path);
if (!$_f->exists()) {
$this->log("\t\t-> " . $child->getClassName());
$generator->parse("om/$targetPlatform/MultiExtendObject.tpl", $path);
} else {
$this->log("\t\t-> (exists) " . $child->getClassName());
}
} // foreach
} // if col->is enumerated
} // if tbl->getChildrenCol
} // if !$table->isForReferenceOnly()
} // foreach table
} // foreach database
} // foreach dataModel
} // main()
}

View File

@ -0,0 +1,287 @@
<?php
/*
* $Id: PropelOldSQLTask.php 3752 2007-04-11 09:11:18Z fabien $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
include_once 'propel/engine/database/model/AppData.php';
/**
* An extended Capsule task used for generating SQL source from an XML schema describing a database structure.
*
* This is deprecated; the new PropelSQLTask should be used instead.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Jason van Zyl <jvanzyl@periapt.com> (Torque)
* @author John McNally <jmcnally@collab.net> (Torque)
* @version $Revision: 536 $
* @package propel.phing
* @deprecated
*/
class PropelOldSQLTask extends AbstractPropelDataModelTask {
/**
* The properties file that maps an SQL file to a particular database.
* @var PhingFile
*/
private $sqldbmap;
/**
* Name of the database.
*/
private $database;
/**
* Set the sqldbmap.
* @param PhingFile $sqldbmap The db map.
*/
public function setSqlDbMap(PhingFile $sqldbmap)
{
$this->sqldbmap = $sqldbmap;
}
/**
* Get the sqldbmap.
* @return PhingFile $sqldbmap.
*/
public function getSqlDbMap()
{
return $this->sqldbmap;
}
/**
* Set the database name.
* @param string $database
*/
public function setDatabase($database)
{
$this->database = $database;
}
/**
* Get the database name.
* @return string
*/
public function getDatabase()
{
return $this->database;
}
/**
* Create the sql -> database map.
*
* @throws IOException - if unable to store properties
*/
private function createSqlDbMap()
{
if ($this->getSqlDbMap() === null) {
return;
}
// Produce the sql -> database map
$sqldbmap = new Properties();
// Check to see if the sqldbmap has already been created.
if ($this->getSqlDbMap()->exists()) {
$sqldbmap->load($this->getSqlDbMap());
}
if ($this->packageObjectModel) {
// in this case we'll get the sql file name from the package attribute
$dataModels = $this->packageDataModels();
foreach ($dataModels as $package => $dataModel) {
foreach ($dataModel->getDatabases() as $database) {
$name = ($package ? $package . '.' : '') . 'schema.xml';
$sqlFile = $this->getMappedFile($name);
$sqldbmap->setProperty($sqlFile->getName(), $database->getName());
}
}
} else {
// the traditional way is to map the schema.xml filenames
$dmMap = $this->getDataModelDbMap();
foreach(array_keys($dmMap) as $dataModelName) {
$sqlFile = $this->getMappedFile($dataModelName);
if ($this->getDatabase() === null) {
$databaseName = $dmMap[$dataModelName];
} else {
$databaseName = $this->getDatabase();
}
$sqldbmap->setProperty($sqlFile->getName(), $databaseName);
}
}
try {
$sqldbmap->store($this->getSqlDbMap(), "Sqlfile -> Database map");
} catch (IOException $e) {
throw new IOException("Unable to store properties: ". $e->getMessage());
}
}
public function main() {
$this->validate();
if(!$this->mapperElement) {
throw new BuildException("You must use a <mapper/> element to describe how names should be transformed.");
}
if ($this->packageObjectModel) {
$dataModels = $this->packageDataModels();
} else {
$dataModels = $this->getDataModels();
}
// 1) first create a map of filenames to databases; this is used by other tasks like
// the SQLExec task.
$this->createSqlDbMap();
// 2) Now actually create the DDL based on the datamodel(s) from XML schema file.
$targetDatabase = $this->getTargetDatabase();
$basepath = "sql/base/$targetDatabase";
$generator = $this->createContext();
$generator->put("basepath", $basepath); // make available to sub-templates
$fname = "sql/base/$targetDatabase/table.tpl" ;
// $generator->put("fname", $fname); // make available to sub-templates
$fnamekeys= "sql/base/$targetDatabase/tablefk.tpl";
//$generator->put("fnamekeys", $fnamekeys); // make available to sub-templates
$ddlStartFile = new PhingFile($this->getTemplatePath(), "sql/base/$targetDatabase/database-start.tpl");
$ddlEndFile = new PhingFile($this->getTemplatePath(), "sql/base/$targetDatabase/database-end.tpl");
foreach ($dataModels as $package => $dataModel) {
foreach ($dataModel->getDatabases() as $database) {
// file we are going to create
if (!$this->packageObjectModel) {
$name = $dataModel->getName();
} else {
$name = ($package ? $package . '.' : '') . 'schema.xml';
}
$outFile = $this->getMappedFile($name);
$generator->put("database", $database); // make available to sub-templates
$generator->put("platform", $database->getPlatform());
$this->log("Generating SQL tables for database: " . $database->getName());
$this->log("Writing to SQL file: " . $outFile->getPath());
// this variable helps us overwrite the first time we write to file
// and then append thereafter
$append=false;
// First check to see if there is a "header" SQL file
if ($ddlStartFile->exists()) {
$generator->parse($ddlStartFile->getAbsolutePath(), $outFile->getAbsolutePath(), false);
$append = true;
}
foreach($database->getTables() as $tbl) {
if (!$tbl->isSkipSql()) {
$this->log("\t + " . $tbl->getName());
$generator->put("table", $tbl);
$generator->parse($fname, $outFile->getAbsolutePath(), $append);
if ($append === false) $append = true;
} else {
$this->log("\t + (skipping) " . $tbl->getName());
}
} // foreach database->getTables()
foreach ($database->getTables() as $tbl) {
if (!$tbl->isSkipSql()) {
$generator->put("tablefk", $tbl);
$generator->parse($fnamekeys, $outFile->getAbsolutePath(), true); // always append
}
}
// Finally check to see if there is a "footer" SQL file
if ($ddlEndFile->exists()) {
$generator->parse($ddlEndFile->getAbsolutePath(), $outFile->getAbsolutePath(), true);
}
} // foreach database
} //foreach datamodels
} // main()
/**
* Packages the datamodels to one datamodel per package
*
* This applies only when the the packageObjectModel option is set. We need to
* re-package the datamodels to allow the database package attribute to control
* which tables go into which SQL file.
*
* @return array The packaged datamodels
*/
protected function packageDataModels() {
static $packagedDataModels;
if (is_null($packagedDataModels)) {
$dataModels = $this->getDataModels();
$dataModel = array_shift($dataModels);
$packagedDataModels = array();
$platform = $this->getPlatformForTargetDatabase();
foreach ($dataModel->getDatabases() as $db) {
foreach ($db->getTables() as $table) {
$package = $table->getPackage();
if (!isset($packagedDataModels[$package])) {
$dbClone = $this->cloneDatabase($db);
$dbClone->setPackage($package);
$ad = new AppData($platform);
$ad->setName($dataModel->getName());
$ad->addDatabase($dbClone);
$packagedDataModels[$package] = $ad;
}
$packagedDataModels[$package]->getDatabase($db->getName())->addTable($table);
}
}
}
return $packagedDataModels;
}
protected function cloneDatabase($db) {
$attributes = array (
'name' => $db->getName(),
'baseClass' => $db->getBaseClass(),
'basePeer' => $db->getBasePeer(),
//'defaultPhpType' => $db->getDefaultPhpType(),
'defaultIdMethod' => $db->getDefaultIdMethod(),
'defaultPhpNamingMethod' => $db->getDefaultPhpNamingMethod(),
'defaultTranslateMethod' => $db->getDefaultTranslateMethod(),
//'heavyIndexing' => $db->getHeavyIndexing(),
);
$clone = new Database();
$clone->loadFromXML($attributes);
return $clone;
}
}

View File

@ -0,0 +1,681 @@
<?php
/*
* $Id: PropelSQLExec.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
require_once 'phing/Task.php';
include_once 'creole/Connection.php';
/**
* Executes all SQL files referenced in the sqldbmap file against their mapped databases.
*
* This task uses an SQL -> Database map in the form of a properties
* file to insert each SQL file listed into its designated database.
*
* @author Hans Lellelid <hans@xmpl.org>
* @author Dominik del Bondio
* @author Jeff Martin <jeff@custommonkey.org> (Torque)
* @author Michael McCallum <gholam@xtra.co.nz> (Torque)
* @author Tim Stephenson <tim.stephenson@sybase.com> (Torque)
* @author Jason van Zyl <jvanzyl@apache.org> (Torque)
* @author Martin Poeschl <mpoeschl@marmot.at> (Torque)
* @version $Revision: 536 $
* @package propel.phing
*/
class PropelSQLExec extends Task {
private $goodSql = 0;
private $totalSql = 0;
const DELIM_ROW = "row";
const DELIM_NORMAL = "normal";
/**
* The delimiter type indicating whether the delimiter will
* only be recognized on a line by itself
*/
private $delimiterType = "normal"; // can't use constant just defined
//private static $delimiterTypes = array(DELIM_NORMAL, DELIM_ROW);
//private static $errorActions = array("continue", "stop", "abort");
/** Database connection */
private $conn = null;
/** Autocommit flag. Default value is false */
private $autocommit = false;
/** SQL statement */
private $statement = null;
/** DB driver. */
private $driver = null;
/** DB url. */
private $url = null;
/** User name. */
private $userId = null;
/** Password */
private $password = null;
/** SQL input command */
private $sqlCommand = "";
/** SQL transactions to perform */
private $transactions = array();
/** SQL Statement delimiter */
private $delimiter = ";";
/** Print SQL results. */
private $print = false;
/** Print header columns. */
private $showheaders = true;
/** Results Output file. */
private $output = null;
/** RDBMS Product needed for this SQL. */
private $rdbms = null;
/** RDBMS Version needed for this SQL. */
private $version = null;
/** Action to perform if an error is found */
private $onError = "abort";
/** Encoding to use when reading SQL statements from a file */
private $encoding = null;
/** Src directory for the files listed in the sqldbmap. */
private $srcDir;
/** Properties file that maps an individual SQL file to a database. */
private $sqldbmap;
/**
* Set the sqldbmap properties file.
*
* @param sqldbmap filename for the sqldbmap
*/
public function setSqlDbMap($sqldbmap)
{
$this->sqldbmap = $this->project->resolveFile($sqldbmap);
}
/**
* Get the sqldbmap properties file.
*
* @return filename for the sqldbmap
*/
public function getSqlDbMap()
{
return $this->sqldbmap;
}
/**
* Set the src directory for the sql files listed in the sqldbmap file.
*
* @param PhingFile $srcDir sql source directory
*/
public function setSrcDir(PhingFile $srcDir)
{
$this->srcDir = $srcDir;
}
/**
* Get the src directory for the sql files listed in the sqldbmap file.
*
* @return PhingFile SQL Source directory
*/
public function getSrcDir()
{
return $this->srcDir;
}
/**
* Set the sql command to execute
*
* @param sql sql command to execute
*/
public function addText($sql)
{
$this->sqlCommand .= $sql;
}
/**
* Set the Creole driver to be used.
*
* @param string $driver driver class name
*/
public function setDriver($driver)
{
$this->driver = $driver;
}
/**
* Set the DB connection url.
*
* @param string $url connection url
*/
public function setUrl($url)
{
$this->url = $url;
}
/**
* Set the user name for the DB connection.
*
* @param string $userId database user
* @deprecated Specify userid in the DSN URL.
*/
public function setUserid($userId)
{
$this->userId = $userId;
}
/**
* Set the password for the DB connection.
*
* @param string $password database password
* @deprecated Specify password in the DSN URL.
*/
public function setPassword($password)
{
$this->password = $password;
}
/**
* Set the autocommit flag for the DB connection.
*
* @param boolean $autocommit the autocommit flag
*/
public function setAutoCommit($autocommit)
{
$this->autocommit = (boolean) $autocommit;
}
/**
* Set the statement delimiter.
*
* <p>For example, set this to "go" and delimitertype to "ROW" for
* Sybase ASE or MS SQL Server.</p>
*
* @param string $delimiter
*/
public function setDelimiter($delimiter)
{
$this->delimiter = $delimiter;
}
/**
* Set the Delimiter type for this sql task. The delimiter type takes two
* values - normal and row. Normal means that any occurence of the delimiter
* terminate the SQL command whereas with row, only a line containing just
* the delimiter is recognized as the end of the command.
*
* @param string $delimiterType
*/
public function setDelimiterType($delimiterType)
{
$this->delimiterType = $delimiterType;
}
/**
* Set the print flag.
*
* @param boolean $print
*/
public function setPrint($print)
{
$this->print = (boolean) $print;
}
/**
* Set the showheaders flag.
*
* @param boolean $showheaders
*/
public function setShowheaders($showheaders)
{
$this->showheaders = (boolean) $showheaders;
}
/**
* Set the output file.
*
* @param PhingFile $output
*/
public function setOutput(PhingFile $output)
{
$this->output = $output;
}
/**
* Set the action to perform onerror
*
* @param string $action
*/
public function setOnerror($action)
{
$this->onError = $action;
}
/**
* Load the sql file and then execute it
*
* @throws BuildException
*/
public function main()
{
$this->sqlCommand = trim($this->sqlCommand);
if ($this->sqldbmap === null || $this->getSqlDbMap()->exists() === false) {
throw new BuildException("You haven't provided an sqldbmap, or "
. "the one you specified doesn't exist: " . $this->sqldbmap->getPath());
}
if ($this->url === null) {
throw new BuildException("DSN url attribute must be set!");
}
$map = new Properties();
try {
$map->load($this->getSqlDbMap());
} catch (IOException $ioe) {
throw new BuildException("Cannot open and process the sqldbmap!");
}
$databases = array();
foreach($map->keys() as $sqlfile) {
$database = $map->getProperty($sqlfile);
// Q: already there?
if (!isset($databases[$database])) {
// A: No.
$databases[$database] = array();
}
// We want to make sure that the base schemas
// are inserted first.
if (strpos($sqlfile, "schema.sql") !== false) {
// add to the beginning of the array
array_unshift($databases[$database], $sqlfile);
} else {
array_push($databases[$database], $sqlfile);
}
}
foreach($databases as $db => $files) {
$transactions = array();
foreach($files as $fileName) {
$file = new PhingFile($this->srcDir, $fileName);
if ($file->exists()) {
$this->log("Executing statements in file: " . $file->__toString());
$transaction = new PropelSQLExecTransaction($this);
$transaction->setSrc($file);
$transactions[] = $transaction;
} else {
$this->log("File '" . $file->__toString()
. "' in sqldbmap does not exist, so skipping it.");
}
}
$this->insertDatabaseSqlFiles($this->url, $db, $transactions);
}
}
/**
* Take the base url, the target database and insert a set of SQL
* files into the target database.
*
* @param string $url
* @param string $database
* @param array $transactions
*/
private function insertDatabaseSqlFiles($url, $database, $transactions)
{
$url = str_replace("@DB@", $database, $url);
$this->log("Our new url -> " . $url);
try {
$buf = "Database settings:\n"
. " driver: " . ($this->driver ? $this->driver : "(default)" ). "\n"
. " URL: " . $url . "\n"
. ($this->userId ? " user: " . $this->userId . "\n" : "")
. ($this->password ? " password: " . $this->password . "\n" : "");
$this->log($buf, PROJECT_MSG_VERBOSE);
$dsn = Creole::parseDSN($url);
if($this->userId) {
$dsn["username"] = $this->userId;
}
if ($this->password) {
$dsn["password"] = $this->password;
}
if ($this->driver) {
Creole::registerDriver($dsn['phptype'], $this->driver);
}
$this->conn = Creole::getConnection($dsn);
$this->conn->setAutoCommit($this->autocommit);
$this->statement = $this->conn->createStatement();
$out = null;
try {
if ($this->output !== null) {
$this->log("Opening PrintStream to output file " . $this->output->__toString(), PROJECT_MSG_VERBOSE);
$out = new FileWriter($this->output);
}
// Process all transactions
for ($i=0,$size=count($transactions); $i < $size; $i++) {
$transactions[$i]->runTransaction($out);
if (!$this->autocommit) {
$this->log("Commiting transaction", PROJECT_MSG_VERBOSE);
$this->conn->commit();
}
}
} catch (Exception $e) {
if ($out) $out->close();
}
} catch (IOException $e) {
if (!$this->autocommit && $this->conn !== null && $this->onError == "abort") {
try {
$this->conn->rollback();
} catch (SQLException $ex) {
// do nothing.
System::println("Rollback failed.");
}
}
if ($this->statement) $this->statement->close();
throw new BuildException($e);
} catch (SQLException $e) {
if (!$this->autocommit && $this->conn !== null && $this->onError == "abort") {
try {
$this->conn->rollback();
} catch (SQLException $ex) {
// do nothing.
System::println("Rollback failed");
}
}
if ($this->statement) $this->statement->close();
throw new BuildException($e);
}
$this->statement->close();
$this->log($this->goodSql . " of " . $this->totalSql
. " SQL statements executed successfully");
}
/**
* Read the statements from the .sql file and execute them.
* Lines starting with '//', '--' or 'REM ' are ignored.
*
* Developer note: must be public in order to be called from
* sudo-"inner" class PropelSQLExecTransaction.
*
* @param Reader $reader
* @param $out Optional output stream.
* @throws SQLException
* @throws IOException
*/
public function runStatements(Reader $reader, $out = null)
{
$sql = "";
$line = "";
$sqlBacklog = "";
$hasQuery = false;
$in = new BufferedReader($reader);
try {
while (($line = $in->readLine()) !== null) {
$line = trim($line);
$line = ProjectConfigurator::replaceProperties($this->project, $line,
$this->project->getProperties());
if (StringHelper::startsWith("//", $line) ||
StringHelper::startsWith("--", $line) ||
StringHelper::startsWith("#", $line)) {
continue;
}
if (strlen($line) > 4
&& strtoupper(substr($line,0, 4)) == "REM ") {
continue;
}
if($sqlBacklog !== "")
{
$sql = $sqlBacklog;
$sqlBacklog = "";
}
$sql .= " " . $line . "\n";
// SQL defines "--" as a comment to EOL
// and in Oracle it may contain a hint
// so we cannot just remove it, instead we must end it
if (strpos($line, "--") !== false) {
$sql .= "\n";
}
// DELIM_ROW doesn't need this (as far as i can tell)
if($this->delimiterType == self::DELIM_NORMAL) {
$reg = "#((?:\"(?:\\\\.|[^\"])*\"?)+|'(?:\\\\.|[^'])*'?|" . preg_quote($this->delimiter) . ")#";
$sqlParts = preg_split($reg, $sql, 0, PREG_SPLIT_DELIM_CAPTURE);
$sqlBacklog = "";
foreach($sqlParts as $sqlPart) {
// we always want to append, even if it's a delim (which will be stripped off later)
$sqlBacklog .= $sqlPart;
// we found a single (not enclosed by ' or ") delimiter, so we can use all stuff before the delim as the actual query
if($sqlPart === $this->delimiter) {
$sql = $sqlBacklog;
$sqlBacklog = "";
$hasQuery = true;
}
}
}
if ($hasQuery || ($this->delimiterType == self::DELIM_ROW && $line == $this->delimiter)) {
// this assumes there is always a delimter on the end of the SQL statement.
$sql = StringHelper::substring($sql, 0, strlen($sql) - 1 - strlen($this->delimiter));
$this->log("SQL: " . $sql, PROJECT_MSG_VERBOSE);
$this->execSQL($sql, $out);
$sql = "";
$hasQuery = false;
}
}
// Catch any statements not followed by ;
if ($sql !== "") {
$this->execSQL($sql, $out);
}
} catch (SQLException $e) {
throw $e;
}
}
/**
* Exec the sql statement.
*
* @param sql
* @param out
* @throws SQLException
*/
protected function execSQL($sql, $out = null)
{
// Check and ignore empty statements
if (trim($sql) == "") {
return;
}
try {
$this->totalSql++;
if (!$this->statement->execute($sql)) {
$this->log($this->statement->getUpdateCount() . " rows affected",
PROJECT_MSG_VERBOSE);
} else {
if ($this->print) {
$this->printResults($out);
}
}
$this->goodSql++;
} catch (SQLException $e) {
$this->log("Failed to execute: " . $sql, PROJECT_MSG_ERR);
if ($this->onError != "continue") {
throw $e;
}
$this->log($e->getMessage(), PROJECT_MSG_ERR);
}
}
/**
* print any results in the statement.
*
* @param out
* @throws SQLException
*/
protected function printResults($out = null)
{
$rs = null;
do {
$rs = $this->statement->getResultSet();
if ($rs !== null) {
$this->log("Processing new result set.", PROJECT_MSG_VERBOSE);
$line = "";
$colsprinted = false;
while ($rs->next()) {
if (!$colsprinted && $this->showheaders) {
$first = true;
foreach($this->fields as $fieldName => $ignore) {
if ($first) $first = false; else $line .= ",";
$line .= $fieldName;
}
} // if show headers
$first = true;
foreach($rs->fields as $columnValue) {
if ($columnValue != null) {
$columnValue = trim($columnValue);
}
if ($first) {
$first = false;
} else {
$line .= ",";
}
$line .= $columnValue;
}
if ($out !== null) {
$out->write($line);
$out->newLine();
}
System::println($line);
$line = "";
} // while rs->next()
}
} while ($this->statement->getMoreResults());
System::println();
if ($out !== null) $out->newLine();
}
}
/**
* "Inner" class that contains the definition of a new transaction element.
* Transactions allow several files or blocks of statements
* to be executed using the same Creole connection and commit
* operation in between.
* @package propel.phing
*/
class PropelSQLExecTransaction {
private $tSrcFile = null;
private $tSqlCommand = "";
private $parent;
function __construct($parent)
{
// Parent is required so that we can log things ...
$this->parent = $parent;
}
public function setSrc(PhingFile $src)
{
$this->tSrcFile = $src;
}
public function addText($sql)
{
$this->tSqlCommand .= $sql;
}
/**
* @throws IOException, SQLException
*/
public function runTransaction($out = null)
{
if (!empty($this->tSqlCommand)) {
$this->parent->log("Executing commands", PROJECT_MSG_INFO);
$this->parent->runStatements($tSqlCommand, $out);
}
if ($this->tSrcFile !== null) {
$this->parent->log("Executing file: " . $this->tSrcFile->getAbsolutePath(),
PROJECT_MSG_INFO);
$reader = new FileReader($this->tSrcFile);
$this->parent->runStatements($reader, $out);
$reader->close();
}
}
}

View File

@ -0,0 +1,258 @@
<?php
/*
* $Id: PropelSQLTask.php 536 2007-01-10 14:30:38Z heltem $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information please see
* <http://propel.phpdb.org>.
*/
include_once 'propel/engine/database/model/AppData.php';
/**
* The task for building SQL DDL based on the XML datamodel.
*
* This class uses the new DDLBuilder classes instead of the Capsule PHP templates.
*
* @author Hans Lellelid <hans@xmpl.org>
* @package propel.phing
*/
class PropelSQLTask extends AbstractPropelDataModelTask {
/**
* The properties file that maps an SQL file to a particular database.
* @var PhingFile
*/
private $sqldbmap;
/**
* Name of the database.
*/
private $database;
/**
* Set the sqldbmap.
* @param PhingFile $sqldbmap The db map.
*/
public function setSqlDbMap(PhingFile $sqldbmap)
{
$this->sqldbmap = $sqldbmap;
}
/**
* Get the sqldbmap.
* @return PhingFile $sqldbmap.
*/
public function getSqlDbMap()
{
return $this->sqldbmap;
}
/**
* Set the database name.
* @param string $database
*/
public function setDatabase($database)
{
$this->database = $database;
}
/**
* Get the database name.
* @return string
*/
public function getDatabase()
{
return $this->database;
}
/**
* Create the sql -> database map.
*
* @throws IOException - if unable to store properties
*/
private function createSqlDbMap()
{
if ($this->getSqlDbMap() === null) {
return;
}
// Produce the sql -> database map
$sqldbmap = new Properties();
// Check to see if the sqldbmap has already been created.
if ($this->getSqlDbMap()->exists()) {
$sqldbmap->load($this->getSqlDbMap());
}
if ($this->packageObjectModel) {
// in this case we'll get the sql file name from the package attribute
$dataModels = $this->packageDataModels();
foreach ($dataModels as $package => $dataModel) {
foreach ($dataModel->getDatabases() as $database) {
$name = ($package ? $package . '.' : '') . 'schema.xml';
$sqlFile = $this->getMappedFile($name);
$sqldbmap->setProperty($sqlFile->getName(), $database->getName());
}
}
} else {
// the traditional way is to map the schema.xml filenames
$dmMap = $this->getDataModelDbMap();
foreach(array_keys($dmMap) as $dataModelName) {
$sqlFile = $this->getMappedFile($dataModelName);
if ($this->getDatabase() === null) {
$databaseName = $dmMap[$dataModelName];
} else {
$databaseName = $this->getDatabase();
}
$sqldbmap->setProperty($sqlFile->getName(), $databaseName);
}
}
try {
$sqldbmap->store($this->getSqlDbMap(), "Sqlfile -> Database map");
} catch (IOException $e) {
throw new IOException("Unable to store properties: ". $e->getMessage());
}
}
public function main() {
$this->validate();
if(!$this->mapperElement) {
throw new BuildException("You must use a <mapper/> element to describe how names should be transformed.");
}
if ($this->packageObjectModel) {
$dataModels = $this->packageDataModels();
} else {
$dataModels = $this->getDataModels();
}
// 1) first create a map of filenames to databases; this is used by other tasks like
// the SQLExec task.
$this->createSqlDbMap();
// 2) Now actually create the DDL based on the datamodel(s) from XML schema file.
$targetDatabase = $this->getTargetDatabase();
DataModelBuilder::setBuildProperties($this->getPropelProperties());
$builderClazz = DataModelBuilder::getBuilderClass('ddl');
foreach ($dataModels as $package => $dataModel) {
foreach ($dataModel->getDatabases() as $database) {
// file we are going to create
if (!$this->packageObjectModel) {
$name = $dataModel->getName();
} else {
$name = ($package ? $package . '.' : '') . 'schema.xml';
}
$outFile = $this->getMappedFile($name);
$this->log("Writing to SQL file: " . $outFile->getPath());
// First add any "header" SQL
$ddl = call_user_func(array($builderClazz, 'getDatabaseStartDDL'));
foreach($database->getTables() as $table) {
if (!$table->isSkipSql()) {
$builder = DataModelBuilder::builderFactory($table, 'ddl');
$this->log("\t+ " . $table->getName() . " [builder: " . get_class($builder) . "]");
$ddl .= $builder->build();
foreach($builder->getWarnings() as $warning) {
$this->log($warning, PROJECT_MSG_WARN);
}
} else {
$this->log("\t + (skipping) " . $table->getName());
}
} // foreach database->getTables()
// Finally check to see if there is any "footer" SQL
$ddl .= call_user_func(array($builderClazz, 'getDatabaseEndDDL'));
// Now we're done. Write the file!
file_put_contents($outFile->getAbsolutePath(), $ddl);
} // foreach database
} //foreach datamodels
} // main()
/**
* Packages the datamodels to one datamodel per package
*
* This applies only when the the packageObjectModel option is set. We need to
* re-package the datamodels to allow the database package attribute to control
* which tables go into which SQL file.
*
* @return array The packaged datamodels
*/
protected function packageDataModels() {
static $packagedDataModels;
if (is_null($packagedDataModels)) {
$dataModels = $this->getDataModels();
$dataModel = array_shift($dataModels);
$packagedDataModels = array();
$platform = $this->getPlatformForTargetDatabase();
foreach ($dataModel->getDatabases() as $db) {
foreach ($db->getTables() as $table) {
$package = $table->getPackage();
if (!isset($packagedDataModels[$package])) {
$dbClone = $this->cloneDatabase($db);
$dbClone->setPackage($package);
$ad = new AppData($platform);
$ad->setName($dataModel->getName());
$ad->addDatabase($dbClone);
$packagedDataModels[$package] = $ad;
}
$packagedDataModels[$package]->getDatabase($db->getName())->addTable($table);
}
}
}
return $packagedDataModels;
}
protected function cloneDatabase($db) {
$attributes = array (
'name' => $db->getName(),
'baseClass' => $db->getBaseClass(),
'basePeer' => $db->getBasePeer(),
//'defaultPhpType' => $db->getDefaultPhpType(),
'defaultIdMethod' => $db->getDefaultIdMethod(),
'defaultPhpNamingMethod' => $db->getDefaultPhpNamingMethod(),
'defaultTranslateMethod' => $db->getDefaultTranslateMethod(),
//'heavyIndexing' => $db->getHeavyIndexing(),
);
$clone = new Database();
$clone->loadFromXML($attributes);
return $clone;
}
}