propelorm/Propel2

src/Propel/Generator/Builder/Om/TableMapBuilder.php
F

Remove call to debugging function var_export

        \$this->addPrimaryKey('$columnName', '$cfc', '".$col->getType()."', ".var_export($col->isNotNull(), true).", ".$size.", $default);";

Remove call to debugging function var_export

        \$this->addColumn('$columnName', '$cfc', '".$col->getType()."', ".var_export($col->isNotNull(), true).", ".$size.", $default);";

Remove call to debugging function var_export

        \$this->getColumn('$columnName')->setValueSet(" . var_export($col->getValueSet(), true). ");";

Remove call to debugging function var_export

            $joinCondition = var_export($fkey->getNormalizedMap($fkey->getMapping()), true);

Remove call to debugging function var_export

            $joinCondition = var_export($fkey->getNormalizedMap($fkey->getMapping()), true);

Remove call to debugging function var_export

                        $string = var_export($value, true);

High overall complexity: 118

<?php

/**
 * This file is part of the Propel package.
 * For the full copyright and license information, please view the LICENSE

When classes take on too many responsibilities, they grow. A large number of instance variables or methods can make a class hard to understand. Large classes tend to have lower cohesion and higher churn.

Often large classes have methods that do not operate on all of the class state. Identifying the groups of data that are used together can point to seams to split out additional collaborator classes or value objects.

Another trick is to look for repeated prefixes or suffixes in method and variable names, or repeated parameter names, and use them to guide extractions.

Refactorings

Further Reading

Complex method in addInitialize

    protected function addInitialize(&$script)
    {

        $table = $this->getTable();
        $platform = $this->getPlatform();

Long or complex methods can make code harder to understand. In most circumstances, methods are best as a small chunk of code (the "how") with a clear, understandable name (the "what"). Long methods can also lead to duplication, as it's harder to reuse logic that is tightly coupled to surrounding code.

Refactorings

Read More

Complex method in addBuildRelations

    protected function addBuildRelations(&$script)
    {
        $script .= "
    /**
     * Build the RelationMap objects for this table relationships

Long or complex methods can make code harder to understand. In most circumstances, methods are best as a small chunk of code (the "how") with a clear, understandable name (the "what"). Long methods can also lead to duplication, as it's harder to reuse logic that is tightly coupled to surrounding code.

Refactorings

Read More

Complex method in addFieldsAttributes

    protected function addFieldsAttributes()
    {
        $tableColumns = $this->getTable()->getColumns();

        $fieldNamesPhpName       = '';

Long or complex methods can make code harder to understand. In most circumstances, methods are best as a small chunk of code (the "how") with a clear, understandable name (the "what"). Long methods can also lead to duplication, as it's harder to reuse logic that is tightly coupled to surrounding code.

Refactorings

Read More

Complex method in addInstancePool

    public function addInstancePool()
    {
        // No need to override instancePool if the PK is not composite
        if (!$this->getTable()->hasCompositePrimaryKey()) {
            return '';

Long or complex methods can make code harder to understand. In most circumstances, methods are best as a small chunk of code (the "how") with a clear, understandable name (the "what"). Long methods can also lead to duplication, as it's harder to reuse logic that is tightly coupled to surrounding code.

Refactorings

Read More

File is too long

<?php

/**
 * This file is part of the Propel package.
 * For the full copyright and license information, please view the LICENSE

Method addInitialize is too long

    protected function addInitialize(&$script)
    {

        $table = $this->getTable();
        $platform = $this->getPlatform();

Method addDoDelete is too long

    protected function addDoDelete(&$script)
    {
        $table = $this->getTable();
        $script .= "
    /**

Method addDoInsert is too long

    protected function addDoInsert(&$script)
    {
        $table = $this->getTable();
        $tableMapClass = $this->getTableMapClass();

Cyclomatic complexity for function addInitialize is too high

    protected function addInitialize(&$script)
    {

        $table = $this->getTable();
        $platform = $this->getPlatform();

Method addGetPrimaryKeyFromRow is too long

    protected function addGetPrimaryKeyFromRow(&$script)
    {
        $script .= "
    /**
     * Retrieves the primary key from the DB resultset row

Method addClassBody is too long

    protected function addClassBody(&$script)
    {
        $table = $this->getTable();

        $this->declareClasses(

Method addPopulateObjects is too long

    protected function addPopulateObjects(&$script)
    {
        $table = $this->getTable();
        $script .= "
    /**

Method addGetOMClass_Inheritance is too long

    protected function addGetOMClass_Inheritance(&$script)
    {
        $col = $this->getTable()->getChildrenColumn();
        $script .= "
    /**

Method addPopulateObject is too long

    protected function addPopulateObject(&$script)
    {
        $table = $this->getTable();
        $script .= "
    /**

Class TableMapBuilder contains too many public methods

class TableMapBuilder extends AbstractOMBuilder
{
    /**
     * Gets the package for the map builder classes.
     * @return string

The variable name, fieldNamesCamelCaseName, is too long

        $fieldNamesCamelCaseName = '';

The variable name, fieldKeysCamelCaseName, is too long

        $fieldKeysCamelCaseName  = '';

The variable name, addInstancePoolKeySnippet, is too long

        $addInstancePoolKeySnippet = $this->getInstancePoolKeySnippet($add);

The variable name, removeInstancePoolKeySnippetObjects, is too long

        $removeInstancePoolKeySnippetObjects = $this->getInstancePoolKeySnippet($removeObjects);

The variable name, removeInstancePoolKeySnippetPks, is too long

        $removeInstancePoolKeySnippetPks = $this->getInstancePoolKeySnippet($removePks);

The variable name, joinedTableTableMapBuilder, is too long

            $joinedTableTableMapBuilder = $this->getNewTableMapBuilder($tblFK)->getTableMapBuilder();

The variable name, i, is too short

            $i = 0;

The variable name, n, is too short

        $n = 0;

The variable name, pk, is too short

        $pk = [];

Identical code found in 1 other location

<?php

/**
 * This file is part of the Propel package.
 * For the full copyright and license information, please view the LICENSE
src/Propel/Generator/Builder/Om/TableMapBuilder.php on lines 518..525

Duplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:

Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.

When you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).

Refactorings

Further Reading

Identical code found in 1 other location

<?php

/**
 * This file is part of the Propel package.
 * For the full copyright and license information, please view the LICENSE
src/Propel/Generator/Builder/Om/TableMapBuilder.php on lines 508..515

Duplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:

Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.

When you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).

Refactorings

Further Reading

There are no issues that match your filters.

<?php

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

namespace Propel\Generator\Builder\Om;

use Propel\Generator\Model\ForeignKey;

use Propel\Generator\Model\IdMethod;
use Propel\Generator\Platform\PlatformInterface;

/**
 * Generates the PHP5 table map class for user object model (OM).
 *
 * @author Hans Lellelid <hans@xmpl.org>
 */
class TableMapBuilder extends AbstractOMBuilder
{
    /**
     * Gets the package for the map builder classes.
     * @return string
     */
    public function getPackage()
    {
        return parent::getPackage() . '.Map';
    }

    public function getNamespace()
    {
        if (!$namespace = parent::getNamespace()) {
            return 'Map';
        }

        if ($this->getGeneratorConfig()
            && $omns = $this->getBuildProperty('generator.objectModel.namespaceMap')) {
            return $namespace . '\\' . $omns;
        }

        return $namespace .'Map';
    }

    public function getBaseTableMapClassName()
    {
        return "TableMap";
    }

    /**
     * Returns the name of the current class being built.
     * @return string
     */
    public function getUnprefixedClassName()
    {
        return $this->getTable()->getPhpName() . 'TableMap';
    }

    /**
     * Adds class phpdoc comment and opening of class.
     * @param string &$script The script will be modified in this method.
     */
    protected function addClassOpen(&$script)
    {
        $table = $this->getTable();
        $script .= "

/**
 * This class defines the structure of the '".$table->getName()."' table.
 *
 *";
        if ($this->getBuildProperty('generator.objectModel.addTimeStamp')) {
            $now = strftime('%c');
            $script .= "
 * This class was autogenerated by Propel " . $this->getBuildProperty('general.version') . " on:
 *
 * $now
 *";
        }
        $script .= "
 *
 * This map class is 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).
 *
 */
class ".$this->getUnqualifiedClassName()." extends TableMap
{
    use InstancePoolTrait;
    use TableMapTrait;

";
    }

    /**
     * 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)
    {
        $table = $this->getTable();

        $this->declareClasses(
            '\Propel\Runtime\ActiveQuery\InstancePoolTrait',
            '\Propel\Runtime\Map\TableMap',
            '\Propel\Runtime\Map\TableMapTrait',
            '\Propel\Runtime\Map\RelationMap',
            '\Propel\Runtime\ActiveQuery\Criteria',
            '\Propel\Runtime\Connection\ConnectionInterface',
            '\Propel\Runtime\Exception\PropelException',
            '\Propel\Runtime\DataFetcher\DataFetcherInterface',
            '\Propel\Runtime\Propel'
        );

        $script .= $this->addConstants();

        $this->addInheritanceColumnConstants($script);
        if ($table->hasValueSetColumns()) {
            $this->addValueSetColumnConstants($script);
        }

        // apply behaviors
        $this->applyBehaviorModifier('staticConstants', $script, "    ");
        $this->applyBehaviorModifier('staticAttributes', $script, "    ");
        $this->applyBehaviorModifier('staticMethods', $script, "    ");

        $this->addAttributes($script);

        $script .= $this->addFieldsAttributes();

        if ($table->hasValueSetColumns()) {
            $this->addValueSetColumnAttributes($script);
            $this->addGetValueSets($script);
            $this->addGetValueSet($script);
        }

        $this->addInitialize($script);
        $this->addBuildRelations($script);
        $this->addGetBehaviors($script);

        $script .= $this->addInstancePool();
        $script .= $this->addClearRelatedInstancePool();

        $this->addGetPrimaryKeyHash($script);
        $this->addGetPrimaryKeyFromRow($script);

        $this->addGetOMClassMethod($script);
        $this->addPopulateObject($script);
        $this->addPopulateObjects($script);

        if (!$table->isAlias()) {
            $this->addSelectMethods($script);
            $this->addGetTableMap($script);
        }

        $this->addBuildTableMap($script);

        $this->addDoDelete($script);
        $this->addDoDeleteAll($script);

        $this->addDoInsert($script);
    }

    /**
     * Adds the addSelectColumns(), doCount(), etc. methods.
     * @param string &$script The script will be modified in this method.
     */
    protected function addSelectMethods(&$script)
    {
        $this->addAddSelectColumns($script);
    }

    /**
     * Adds any constants needed for this TableMap class.
     *
     * @return string
     */
    protected function addConstants()
    {
        return $this->renderTemplate('tableMapConstants', [
            'className'         => $this->getClasspath(),
            'dbName'            => $this->getDatabase()->getName(),
            'tableName'         => $this->getTable()->getName(),
            'tablePhpName'      => $this->getTable()->isAbstract() ? '' : addslashes($this->getStubObjectBuilder()->getFullyQualifiedClassName()),
            'classPath'         => $this->getStubObjectBuilder()->getClasspath(),
            'nbColumns'         => $this->getTable()->getNumColumns(),
            'nbLazyLoadColumns' => $this->getTable()->getNumLazyLoadColumns(),
            'nbHydrateColumns'  => $this->getTable()->getNumColumns() - $this->getTable()->getNumLazyLoadColumns(),
            'columns'           => $this->getTable()->getColumns(),
            'stringFormat'      => $this->getTable()->getDefaultStringFormat(),
        ]);
    }

    /**
     * Adds the COLUMN_NAME constant to the class definition.
     * @param string &$script The script will be modified in this method.
     */
    protected function addColumnNameConstants(&$script)
    {
        foreach ($this->getTable()->getColumns() as $col) {
            $script .= "
    /**
     * the column name for the " . $col->getName() ." field
     */
    const ".$col->getConstantName() ." = '" . $this->getTable()->getName() . ".".$col->getName()."';
";
        } // foreach
    }

    /**
     * Adds the valueSet constants for ENUM and SET columns.
     * @param string &$script The script will be modified in this method.
     */
    protected function addValueSetColumnConstants(&$script)
    {
        foreach ($this->getTable()->getColumns() as $col) {
            if ($col->isValueSetType()) {
                $script .= "
    /** The enumerated values for the " . $col->getName() . " field */";
                foreach ($col->getValueSet() as $value) {
                    $script .= "
    const " . $col->getConstantName() . '_' . $this->getValueSetConstant($value) . " = '" . $value . "';";
                }
                $script .= "
";
            }
        }
    }

    /**
     * Adds the valueSet attributes for ENUM columns.
     * @param string &$script The script will be modified in this method.
     */
    protected function addValueSetColumnAttributes(&$script)
    {
        $script .= "
    /** The enumerated values for this table */
    protected static \$enumValueSets = array(";
        foreach ($this->getTable()->getColumns() as $col) {
            if ($col->isValueSetType()) {
                $script .= "
                {$col->getFQConstantName()} => array(
                ";
                foreach ($col->getValueSet() as $value) {
                    $script .= "            self::" . $col->getConstantName() . '_' . $this->getValueSetConstant($value) . ",
";
                }
                $script .= "        ),";
            }
        }
        $script .= "
    );
";
    }

    /**
     * Adds the getValueSets() method.
     * @param string &$script The script will be modified in this method.
     */
    protected function addGetValueSets(&$script)
    {
        $script .= "
    /**
     * Gets the list of values for all ENUM and SET columns
     * @return array
     */
    public static function getValueSets()
    {
      return static::\$enumValueSets;
    }
";
    }

    /**
     * Adds the getValueSet() method.
     * @param string &$script The script will be modified in this method.
     */
    protected function addGetValueSet(&$script)
    {
        $script .= "
    /**
     * Gets the list of values for an ENUM or SET column
     * @param string \$colname
     * @return array list of possible values for the column
     */
    public static function getValueSet(\$colname)
    {
        \$valueSets = self::getValueSets();

        return \$valueSets[\$colname];
    }
";
    }

    /**
     * Adds the CLASSKEY_* and CLASSNAME_* constants used for inheritance.
     * @param string &$script The script will be modified in this method.
     */
    public function addInheritanceColumnConstants(&$script)
    {
        if (!$col = $this->getTable()->getChildrenColumn()) {
            return;
        }

        if (!$col->isEnumeratedClasses()) {
            return;
        }

        foreach ($col->getChildren() as $child) {
            $childBuilder = $this->getMultiExtendObjectBuilder();
            $childBuilder->setChild($child);
            $fqcn = addslashes($childBuilder->getFullyQualifiedClassName());

            $script .= "
    /** A key representing a particular subclass */
    const CLASSKEY_".$child->getConstantSuffix()." = '" . $child->getKey() . "';
";

            if (strtoupper($child->getClassName()) != $child->getConstantSuffix()) {
                $script .= "
    /** A key representing a particular subclass */
    const CLASSKEY_".strtoupper($child->getClassname())." = '" . $fqcn . "';
";
            }

            $script .= "
    /** A class that can be returned by this tableMap. */
    const CLASSNAME_".$child->getConstantSuffix()." = '". $fqcn . "';
";
        }
    }

    /**
     * @param  string $value
     * @return string
     */
    protected function getValueSetConstant($value)
    {
        return strtoupper(preg_replace('/[^a-zA-Z0-9_\x7f-\xff]/', '_', $value));
    }

    /**
     * Adds any attributes needed for this TableMap class.
     * @param string &$script The script will be modified in this method.
     */
    protected function addAttributes(&$script)
    {
    }

    protected function addFieldsAttributes()
    {
        $tableColumns = $this->getTable()->getColumns();

        $fieldNamesPhpName       = '';
        $fieldNamesCamelCaseName = '';
        $fieldNamesColname       = '';
        $fieldNamesRawColname    = '';
        $fieldNamesFieldName     = '';
        $fieldNamesNum           = '';

        $fieldKeysPhpName        = '';
        $fieldKeysCamelCaseName  = '';
        $fieldKeysColname        = '';
        $fieldKeysRawColname     = '';
        $fieldKeysFieldName      = '';
        $fieldKeysNum            = '';

        foreach ($tableColumns as $num => $col) {
            $fieldNamesPhpName       .= "'" . $col->getPhpName() . "', ";
            $fieldNamesCamelCaseName .= "'" . $col->getCamelCaseName() . "', ";
            $fieldNamesColname       .= $this->getColumnConstant($col, $this->getTableMapClass()) . ", ";
            $fieldNamesRawColname    .= "'" . $col->getConstantName() . "', ";
            $fieldNamesFieldName     .= "'" . $col->getName() . "', ";
            $fieldNamesNum           .= "$num, ";

            $fieldKeysPhpName        .= "'" . $col->getPhpName() . "' => $num, ";
            $fieldKeysCamelCaseName  .= "'" . $col->getCamelCaseName() . "' => $num, ";
            $fieldKeysColname        .= $this->getColumnConstant($col, $this->getTableMapClass())." => $num, ";
            $fieldKeysRawColname     .= "'" . $col->getConstantName() . "' => $num, ";
            $fieldKeysFieldName      .= "'" . $col->getName() . "' => $num, ";
            $fieldKeysNum            .= "$num, ";
        }

        return $this->renderTemplate('tableMapFields', [
                'fieldNamesPhpName'       => $fieldNamesPhpName,
                'fieldNamesCamelCaseName' => $fieldNamesCamelCaseName,
                'fieldNamesColname'       => $fieldNamesColname,
                'fieldNamesRawColname'    => $fieldNamesRawColname,
                'fieldNamesFieldName'     => $fieldNamesFieldName,
                'fieldNamesNum'           => $fieldNamesNum,
                'fieldKeysPhpName'        => $fieldKeysPhpName,
                'fieldKeysCamelCaseName'  => $fieldKeysCamelCaseName,
                'fieldKeysColname'        => $fieldKeysColname,
                'fieldKeysRawColname'     => $fieldKeysRawColname,
                'fieldKeysFieldName'      => $fieldKeysFieldName,
                'fieldKeysNum'            => $fieldKeysNum,
        ]);
    }

    /**
     * Closes class.
     * @param string &$script The script will be modified in this method.
     */
    protected function addClassClose(&$script)
    {
        $script .= "
} // " . $this->getUnqualifiedClassName() . "
// This is the static code needed to register the TableMap for this table with the main Propel class.
//
".$this->getUnqualifiedClassName()."::buildTableMap();
";
        $this->applyBehaviorModifier('tableMapFilter', $script, "");
    }

    /**
     * Adds the buildTableMap() method.
     * @param string &$script The script will be modified in this method.
     */
    protected function addBuildTableMap(&$script)
    {
        $this->declareClassFromBuilder($this->getTableMapBuilder());
        $script .= "
    /**
     * Add a TableMap instance to the database for this tableMap class.
     */
    public static function buildTableMap()
    {
        \$dbMap = Propel::getServiceContainer()->getDatabaseMap(" . $this->getTableMapClass() . "::DATABASE_NAME);
        if (!\$dbMap->hasTable(" . $this->getTableMapClass() . "::TABLE_NAME)) {
            \$dbMap->addTableObject(new ".$this->getTableMapClass()."());
        }
    }
";
    }

    /**
     * Adds the addInitialize() method to the  table map class.
     * @param string &$script The script will be modified in this method.
     */
    protected function addInitialize(&$script)
    {

        $table = $this->getTable();
        $platform = $this->getPlatform();

        $script .= "
    /**
     * Initialize the table attributes and columns
     * Relations are not initialized by this method since they are lazy loaded
     *
     * @return void
     * @throws PropelException
     */
    public function initialize()
    {
        // attributes
        \$this->setName('".$table->getName()."');
        \$this->setPhpName('".$table->getPhpName()."');
        \$this->setIdentifierQuoting(".($table->isIdentifierQuotingEnabled() ? 'true' : 'false').");
        \$this->setClassName('" . addslashes($this->getStubObjectBuilder()->getFullyQualifiedClassName()) . "');
        \$this->setPackage('" . parent::getPackage() . "');";
        if ($table->getIdMethod() == "native") {
            $script .= "
        \$this->setUseIdGenerator(true);";
        } else {
            $script .= "
        \$this->setUseIdGenerator(false);";
        }

        if ($table->getIdMethodParameters()) {
            $params = $table->getIdMethodParameters();
            $imp = $params[0];
            $script .= "
        \$this->setPrimaryKeyMethodInfo('".$imp->getValue()."');";
        } elseif ($table->getIdMethod() == IdMethod::NATIVE && ($platform->getNativeIdMethod() == PlatformInterface::SEQUENCE || $platform->getNativeIdMethod() == PlatformInterface::SERIAL)) {
            $script .= "
        \$this->setPrimaryKeyMethodInfo('".$platform->getSequenceName($table)."');";
        }

        if ($this->getTable()->getChildrenColumn()) {
            $script .= "
        \$this->setSingleTableInheritance(true);";
        }

        if ($this->getTable()->getIsCrossRef()) {
            $script .= "
        \$this->setIsCrossRef(true);";
        }

        // Add columns to map
            $script .= "
        // columns";
        foreach ($table->getColumns() as $col) {
            $columnName = $col->getName();
            $cfc = $col->getPhpName();
            if (!$col->getSize()) {
                $size = "null";
            } else {
                $size = $col->getSize();
            }
            $default = $col->getDefaultValueString();
            if ($col->isPrimaryKey()) {
                if ($col->isForeignKey()) {
                    foreach ($col->getForeignKeys() as $fk) {
                        $script .= "
        \$this->addForeignPrimaryKey('$columnName', '$cfc', '".$col->getType()."' , '".$fk->getForeignTableName()."', '".$fk->getMappedForeignColumn($col->getName())."', ".($col->isNotNull() ? 'true' : 'false').", ".$size.", $default);";
                    }
                } else {
                    $script .= "
        \$this->addPrimaryKey('$columnName', '$cfc', '".$col->getType()."', ".var_export($col->isNotNull(), true).", ".$size.", $default);";
                }
            } else {
                if ($col->isForeignKey()) {
                    foreach ($col->getForeignKeys() as $fk) {
                        $script .= "
        \$this->addForeignKey('$columnName', '$cfc', '".$col->getType()."', '".$fk->getForeignTableName()."', '".$fk->getMappedForeignColumn($col->getName())."', ".($col->isNotNull() ? 'true' : 'false').", ".$size.", $default);";
                    }
                } else {
                    $script .= "
        \$this->addColumn('$columnName', '$cfc', '".$col->getType()."', ".var_export($col->isNotNull(), true).", ".$size.", $default);";
                }
            } // if col-is prim key
            if ($col->isValueSetType()) {
                $script .= "
        \$this->getColumn('$columnName')->setValueSet(" . var_export($col->getValueSet(), true). ");";
            }
            if ($col->isPrimaryString()) {
                $script .= "
        \$this->getColumn('$columnName')->setPrimaryString(true);";
            }
        } // foreach

        $script .= "
    } // initialize()
";

    }

    /**
     * Adds the method that build the RelationMap objects
     * @param string &$script The script will be modified in this method.
     */
    protected function addBuildRelations(&$script)
    {
        $script .= "
    /**
     * Build the RelationMap objects for this table relationships
     */
    public function buildRelations()
    {";
        foreach ($this->getTable()->getForeignKeys() as $fkey) {
            $joinCondition = var_export($fkey->getNormalizedMap($fkey->getMapping()), true);
            $onDelete = $fkey->hasOnDelete() ? "'" . $fkey->getOnDelete() . "'" : 'null';
            $onUpdate = $fkey->hasOnUpdate() ? "'" . $fkey->getOnUpdate() . "'" : 'null';
            $isPolymorphic = $fkey->isPolymorphic() ? 'true' : 'false';
            $script .= "
        \$this->addRelation('" . $this->getFKPhpNameAffix($fkey) . "', '" . addslashes($this->getNewStubObjectBuilder($fkey->getForeignTable())->getFullyQualifiedClassName()) . "', RelationMap::MANY_TO_ONE, $joinCondition, $onDelete, $onUpdate, null, $isPolymorphic);";
        }

        foreach ($this->getTable()->getReferrers() as $fkey) {
            $relationName = $this->getRefFKPhpNameAffix($fkey);
            $joinCondition = var_export($fkey->getNormalizedMap($fkey->getMapping()), true);
            $onDelete = $fkey->hasOnDelete() ? "'" . $fkey->getOnDelete() . "'" : 'null';
            $onUpdate = $fkey->hasOnUpdate() ? "'" . $fkey->getOnUpdate() . "'" : 'null';
            $isPolymorphic = $fkey->isPolymorphic() ? 'true' : 'false';
            $script .= "
        \$this->addRelation('$relationName', '" . addslashes($this->getNewStubObjectBuilder($fkey->getTable())->getFullyQualifiedClassName()) . "', RelationMap::ONE_TO_" . ($fkey->isLocalPrimaryKey() ? "ONE" : "MANY") .", $joinCondition, $onDelete, $onUpdate";
            if ($fkey->isLocalPrimaryKey()) {
                 $script .= ", null";
            } else {
                $script .= ", '" . $this->getRefFKPhpNameAffix($fkey, true) . "'";
            }

            $script .= ", $isPolymorphic);";
        }

        foreach ($this->getTable()->getCrossFks() as $crossFKs) {
            foreach ($crossFKs->getCrossForeignKeys() as $crossFK) {
                $relationName = $this->getFKPhpNameAffix($crossFK);
                $pluralName = "'" . $this->getFKPhpNameAffix($crossFK, true) . "'";
                $onDelete = $crossFK->hasOnDelete() ? "'" . $crossFK->getOnDelete() . "'" : 'null';
                $onUpdate = $crossFK->hasOnUpdate() ? "'" . $crossFK->getOnUpdate() . "'" : 'null';
                $script .= "
        \$this->addRelation('$relationName', '" . addslashes($this->getNewStubObjectBuilder($crossFK->getForeignTable())->getFullyQualifiedClassName()) . "', RelationMap::MANY_TO_MANY, array(), $onDelete, $onUpdate, $pluralName);";
            }
        }
        $script .= "
    } // buildRelations()
";
    }

    /**
     * Adds the behaviors getter
     * @param string &$script The script will be modified in this method.
     */
    protected function addGetBehaviors(&$script)
    {
        $behaviors = $this->getTable()->getBehaviors();
        if ($behaviors) {
            $script .= "
    /**
     *
     * Gets the list of behaviors registered for this table
     *
     * @return array Associative array (name => parameters) of behaviors
     */
    public function getBehaviors()
    {
        return array(";
            foreach ($behaviors as $behavior) {
                $script .= "
            '{$behavior->getId()}' => array(";
                foreach ($behavior->getParameters() as $key => $value) {
                    $script .= "'$key' => ";
                    if (is_array($value)) {
                        $string = var_export($value, true);
                        $string = str_replace("\n", '', $string);
                        $string = str_replace('  ', '', $string);
                        $script .= $string.", ";
                    } else {
                        $script .= "'$value', ";
                    }
                }
                $script .= "),";
            }
            $script .= "
        );
    } // getBehaviors()
";
        }
    }

    /**
     * Adds the PHP code to return a instance pool key for the passed-in primary key variable names.
     *
     * @param  array  $pkphp An array of PHP var names / method calls representing complete pk.
     * @return string
     */
    public function getInstancePoolKeySnippet($pkphp)
    {
        $pkphp = (array) $pkphp; // make it an array if it is not.
        $script = '';
        if (count($pkphp) > 1) {
            $script .= "serialize([";
            $i = 0;
            foreach ($pkphp as $pkvar) {
                $script .= ($i++ ? ', ' : '') . "(null === {$pkvar} || is_scalar({$pkvar}) || is_callable([{$pkvar}, '__toString']) ? (string) {$pkvar} : {$pkvar})";
            }
            $script .= "])";
        } else {
            $script .= "null === {$pkphp[0]} || is_scalar({$pkphp[0]}) || is_callable([{$pkphp[0]}, '__toString']) ? (string) {$pkphp[0]} : {$pkphp[0]}";
        }

        return $script;
    }

    public function addInstancePool()
    {
        // No need to override instancePool if the PK is not composite
        if (!$this->getTable()->hasCompositePrimaryKey()) {
            return '';
        }

        $pks = $this->getTable()->getPrimaryKey();

        if (!count($pks)) {
            return;
        }

        $add = [];
        $removeObjects = [];
        foreach ($pks as $pk) {
            $add[] = '$obj->get' . $pk->getPhpName() . '()';
            $removeObjects[] = '$value->get' . $pk->getPhpName() . '()';
        }
        $addInstancePoolKeySnippet = $this->getInstancePoolKeySnippet($add);
        $removeInstancePoolKeySnippetObjects = $this->getInstancePoolKeySnippet($removeObjects);

        $removePks = [];
        $nbPks = count($pks);
        for ($i = 0; $i < $nbPks; $i++) {
            $removePks[] = "\$value[$i]";
        }
        $removeInstancePoolKeySnippetPks = $this->getInstancePoolKeySnippet($removePks);

        return $this->renderTemplate('tableMapInstancePool', [
                'objectClassName'                     => $this->getStubObjectBuilder()->getClassName(),
                'addInstancePoolKeySnippet'           => $addInstancePoolKeySnippet,
                'removeInstancePoolKeySnippetObjects' => $removeInstancePoolKeySnippetObjects,
                'removeInstancePoolKeySnippetPks'     => $removeInstancePoolKeySnippetPks,
                'countPks'                            => count($pks)
        ]);
    }

    public function addClearRelatedInstancePool()
    {
        $table = $this->getTable();
        $relatedClassNames = [];

        // Handle ON DELETE CASCADE for updating instance pool
        foreach ($table->getReferrers() as $fk) {
            // $fk is the foreign key in the other table, so localTableName will
            // actually be the table name of other table
            $tblFK = $fk->getTable();

            $joinedTableTableMapBuilder = $this->getNewTableMapBuilder($tblFK)->getTableMapBuilder();
            $tableMapClassName = $this->declareClassFromBuilder($joinedTableTableMapBuilder, true);

            if (!$tblFK->isForReferenceOnly()) {
                // we can't perform operations on tables that are
                // not within the schema (i.e. that we have no map for, etc.)

                if (ForeignKey::CASCADE === $fk->getOnDelete()  || ForeignKey::SETNULL === $fk->getOnDelete()) {
                    $relatedClassNames[$tableMapClassName] = $tableMapClassName;
                }
            }
        }

        if (0 == count($relatedClassNames)) {
            return '';
        }

        return $this->renderTemplate('tableMapClearRelatedInstancePool', [
            'tableName'           => $table->getName(),
            'relatedClassNames'   => $relatedClassNames,
        ]);
    }

    /**
     * Checks whether any registered behavior on that table has a modifier for a hook
     * @param  string  $hookName The name of the hook as called from one of this class methods, e.g. "preSave"
     * @param  null    $modifier
     * @return boolean
     */
    public function hasBehaviorModifier($hookName, $modifier = null)
    {
        return parent::hasBehaviorModifier($hookName, 'TableMapBuilderModifier');
    }

    /**
     * Checks whether any registered behavior on that table has a modifier for a hook
     * @param string $hookName The name of the hook as called from one of this class methods, e.g. "preSave"
     * @param string &$script  The script will be modified in this method.
     * @param string $tab
     */
    public function applyBehaviorModifier($hookName, &$script, $tab = "        ")
    {
        $this->applyBehaviorModifierBase($hookName, 'TableMapBuilderModifier', $script, $tab);
    }

    /**
     * Adds method to get a version of the primary key that can be used as a unique key for identifier map.
     *
     * @param string &$script The script will be modified in this method.
     */
    protected function addGetPrimaryKeyHash(&$script)
    {
        // We have to iterate through all the columns so that we know the offset of the primary
        // key columns.
        $n = 0;
        $pk = [];
        $cond = [];
        foreach ($this->getTable()->getColumns() as $col) {
            if (!$col->isLazyLoad()) {
                if ($col->isPrimaryKey()) {
                    $part = "\$row[TableMap::TYPE_NUM == \$indexType ? $n + \$offset : static::translateFieldName('{$col->getPhpName()}', TableMap::TYPE_PHPNAME, \$indexType)]";
                    $cond[] = $part . " === null";
                    $pk[] = $part;
                }
                $n++;
            }
        }

        $script .= "
    /**
     * Retrieves a string version of the primary key from the DB resultset row that can be used to uniquely identify a row in this table.
     *
     * For tables with a single-column primary key, that simple pkey value will be returned.  For tables with
     * a multi-column primary key, a serialize()d version of the primary key will be returned.
     *
     * @param array  \$row       resultset row.
     * @param int    \$offset    The 0-based offset for reading from the resultset row.
     * @param string \$indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_CAMELNAME
     *                           TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM
     *
     * @return string The primary key hash of the row
     */
    public static function getPrimaryKeyHashFromRow(\$row, \$offset = 0, \$indexType = TableMap::TYPE_NUM)
    {";
        if (count($pk) > 0) {
            $script .= "
        // If the PK cannot be derived from the row, return NULL.
        if (".implode(' && ', $cond).") {
            return null;
        }

        return ".$this->getInstancePoolKeySnippet($pk).";
    }
";
        } else {
            $script .= "
        return null;
    }
";
        }
    }

    /**
     * Adds method to get the primary key from a row
     * @param string &$script The script will be modified in this method.
     */
    protected function addGetPrimaryKeyFromRow(&$script)
    {
        $script .= "
    /**
     * Retrieves the primary key from the DB resultset row
     * For tables with a single-column primary key, that simple pkey value will be returned.  For tables with
     * a multi-column primary key, an array of the primary key columns will be returned.
     *
     * @param array  \$row       resultset row.
     * @param int    \$offset    The 0-based offset for reading from the resultset row.
     * @param string \$indexType One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_CAMELNAME
     *                           TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM
     *
     * @return mixed The primary key of the row
     */
    public static function getPrimaryKeyFromRow(\$row, \$offset = 0, \$indexType = TableMap::TYPE_NUM)
    {";

        // We have to iterate through all the columns so that we
        // know the offset of the primary key columns.
        $table = $this->getTable();
        $n = 0;

        if ($table->hasCompositePrimaryKey()) {
            $script .= "
            \$pks = [];
            ";

            $pks = [];
            foreach ($table->getColumns() as $col) {
                if (!$col->isLazyLoad()) {
                    if ($col->isPrimaryKey()) {
                        $script .= '
        $pks[] = (' . $col->getPhpType() . ') ' . "\$row[
            \$indexType == TableMap::TYPE_NUM
                ? $n + \$offset
                : self::translateFieldName('{$col->getPhpName()}', TableMap::TYPE_PHPNAME, \$indexType)
        ];";
                    }
                    $n++;
                }
            }

            $script .= "

        return \$pks;";
        } else {

            $pk = "''";
            foreach ($table->getColumns() as $col) {
                if (!$col->isLazyLoad()) {
                    if ($col->isPrimaryKey()) {
                        $pk = '(' . $col->getPhpType() . ') ' . "\$row[
            \$indexType == TableMap::TYPE_NUM
                ? $n + \$offset
                : self::translateFieldName('{$col->getPhpName()}', TableMap::TYPE_PHPNAME, \$indexType)
        ]";
                    }
                    $n++;
                }
            }

            $script .= "
        return " . $pk . ";";
        }

        $script .= "
    }
    ";
    }

    /**
     * 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()) {
            $this->addGetOMClass_Inheritance($script);
        } else {
            if ($table->isAbstract()) {
                $this->addGetOMClass_NoInheritance_Abstract($script);
            } else {
                $this->addGetOMClass_NoInheritance($script);
            }
        }
    }

    /**
     * Adds a getOMClass() for non-abstract tables that have inheritance.
     * @param string &$script The script will be modified in this method.
     */
    protected function addGetOMClass_Inheritance(&$script)
    {
        $col = $this->getTable()->getChildrenColumn();
        $script .= "
    /**
     * The returned Class will contain objects of the default type or
     * objects that inherit from the default.
     *
     * @param array   \$row ConnectionInterface result row.
     * @param int     \$colnum Column to examine for OM class information (first is 0).
     * @param boolean \$withPrefix Whether or not to return the path with the class name
     * @throws PropelException Any exceptions caught during processing will be
     *                         rethrown wrapped into a PropelException.
     *
     * @return string The OM class
     */
    public static function getOMClass(\$row, \$colnum, \$withPrefix = true)
    {
        try {
";
        if ($col->isEnumeratedClasses()) {
            $script .= "
            \$omClass = null;
            \$classKey = \$row[\$colnum + " . ($col->getPosition() - 1) . "];

            switch (\$classKey) {
";
            foreach ($col->getChildren() as $child) {
                $script .= "
                case {$this->getTableMapClassName()}::CLASSKEY_".$child->getConstantSuffix().":
                    \$omClass = {$this->getTableMapClassName()}::CLASSNAME_".$child->getConstantSuffix().";
                    break;
";
            } /* foreach */
            $script .= "
                default:
                    \$omClass = {$this->getTableMapClassName()}::CLASS_DEFAULT;
";
            $script .= "
            } // switch
            if (!\$withPrefix) {
                \$omClass = preg_replace('#\.#', '\\\\', \$omClass);
            }
";
        } else { /* if not enumerated */
            $script .= "
            \$omClass = \$row[\$colnum + ".($col->getPosition()-1)."];
            \$omClass = preg_replace('#\.#', '\\\\', '.'.\$omClass);
";
        }
        $script .= "
        } catch (\Exception \$e) {
            throw new PropelException('Unable to get OM class.', \$e);
        }

        return \$omClass;
    }
";
    }

    /**
     * Adds a getOMClass() for non-abstract tables that do note use inheritance.
     * @param string &$script The script will be modified in this method.
     */
    protected function addGetOMClass_NoInheritance(&$script)
    {
        $script .= "
    /**
     * The class that the tableMap will make instances of.
     *
     * If \$withPrefix is true, the returned path
     * uses a dot-path notation which is translated into a path
     * relative to a location on the PHP include_path.
     * (e.g. path.to.MyClass -> 'path/to/MyClass.php')
     *
     * @param boolean \$withPrefix Whether or not to return the path with the class name
     * @return string path.to.ClassName
     */
    public static function getOMClass(\$withPrefix = true)
    {
        return \$withPrefix ? " . $this->getTableMapClass() . "::CLASS_DEFAULT : " . $this->getTableMapClass() . "::OM_CLASS;
    }
";
    }

    /**
     * Adds a getOMClass() signature for abstract tables that do not have inheritance.
     * @param string &$script The script will be modified in this method.
     */
    protected function addGetOMClass_NoInheritance_Abstract(&$script)
    {
        $script .= "
    /**
     * The class that the tableMap will make instances of.
     *
     * This method must be overridden by the stub subclass, because
     * ".$this->getObjectClassName()." is declared abstract in the schema.
     *
     * @param boolean \$withPrefix
     */
    abstract public static function getOMClass(\$withPrefix = true);
";
    }



    /**
     * Adds the populateObject() method.
     * @param string &$script The script will be modified in this method.
     */
    protected function addPopulateObject(&$script)
    {
        $table = $this->getTable();
        $script .= "
    /**
     * Populates an object of the default type or an object that inherit from the default.
     *
     * @param array  \$row       row returned by DataFetcher->fetch().
     * @param int    \$offset    The 0-based offset for reading from the resultset row.
     * @param string \$indexType The index type of \$row. Mostly DataFetcher->getIndexType().
                                 One of the class type constants TableMap::TYPE_PHPNAME, TableMap::TYPE_CAMELNAME
     *                           TableMap::TYPE_COLNAME, TableMap::TYPE_FIELDNAME, TableMap::TYPE_NUM.
     *
     * @throws PropelException Any exceptions caught during processing will be
     *                         rethrown wrapped into a PropelException.
     * @return array           (" . $this->getObjectClassName(). " object, last column rank)
     */
    public static function populateObject(\$row, \$offset = 0, \$indexType = TableMap::TYPE_NUM)
    {
        \$key = {$this->getTableMapClassName()}::getPrimaryKeyHashFromRow(\$row, \$offset, \$indexType);
        if (null !== (\$obj = {$this->getTableMapClassName()}::getInstanceFromPool(\$key))) {
            // We no longer rehydrate the object, since this can cause data loss.
            // See http://www.propelorm.org/ticket/509
            // \$obj->hydrate(\$row, \$offset, true); // rehydrate
            \$col = \$offset + " . $this->getTableMapClass() . "::NUM_HYDRATE_COLUMNS;";
        if ($table->isAbstract()) {
            $script .= "
        } elseif (null == \$key) {
            // empty resultset, probably from a left join
            // since this table is abstract, we can't hydrate an empty object
            \$obj = null;
            \$col = \$offset + " . $this->getTableMapClass() . "::NUM_HYDRATE_COLUMNS;";
        }
        $script .= "
        } else {";
        if (!$table->getChildrenColumn()) {
            $script .= "
            \$cls = " . $this->getTableMapClass() . "::OM_CLASS;";
        } else {
            $script .= "
            \$cls = static::getOMClass(\$row, \$offset, false);";
        }
        $script .= "
            /** @var {$this->getObjectClassName()} \$obj */
            \$obj = new \$cls();
            \$col = \$obj->hydrate(\$row, \$offset, false, \$indexType);
            {$this->getTableMapClassName()}::addInstanceToPool(\$obj, \$key);
        }

        return array(\$obj, \$col);
    }
";
    }

    /**
     * Adds the populateObjects() method.
     * @param string &$script The script will be modified in this method.
     */
    protected function addPopulateObjects(&$script)
    {
        $table = $this->getTable();
        $script .= "
    /**
     * The returned array will contain objects of the default type or
     * objects that inherit from the default.
     *
     * @param DataFetcherInterface \$dataFetcher
     * @return array
     * @throws PropelException Any exceptions caught during processing will be
     *                         rethrown wrapped into a PropelException.
     */
    public static function populateObjects(DataFetcherInterface \$dataFetcher)
    {
        \$results = array();
    ";
        if (!$table->getChildrenColumn()) {
            $script .= "
        // set the class once to avoid overhead in the loop
        \$cls = static::getOMClass(false);";
        }

        $script .= "
        // populate the object(s)
        while (\$row = \$dataFetcher->fetch()) {
            \$key = {$this->getTableMapClassName()}::getPrimaryKeyHashFromRow(\$row, 0, \$dataFetcher->getIndexType());
            if (null !== (\$obj = {$this->getTableMapClassName()}::getInstanceFromPool(\$key))) {
                // We no longer rehydrate the object, since this can cause data loss.
                // See http://www.propelorm.org/ticket/509
                // \$obj->hydrate(\$row, 0, true); // rehydrate
                \$results[] = \$obj;
            } else {"
        ;

        if ($table->getChildrenColumn()) {
            $script .= "
                // class must be set each time from the record row
                \$cls = static::getOMClass(\$row, 0);
                \$cls = preg_replace('#\.#', '\\\\', \$cls);
                /** @var {$this->getObjectClassName()} \$obj */
                " . $this->buildObjectInstanceCreationCode('$obj', '$cls') . "
                \$obj->hydrate(\$row);
                \$results[] = \$obj;
                {$this->getTableMapClassName()}::addInstanceToPool(\$obj, \$key);";
        } else {
            $script .= "
                /** @var {$this->getObjectClassName()} \$obj */
                " . $this->buildObjectInstanceCreationCode('$obj', '$cls') . "
                \$obj->hydrate(\$row);
                \$results[] = \$obj;
                {$this->getTableMapClassName()}::addInstanceToPool(\$obj, \$key);";
        }
        $script .= "
            } // if key exists
        }

        return \$results;
    }";
    }

    /**
     * Adds the addSelectColumns() method.
     * @param string &$script The script will be modified in this method.
     */
    protected function addAddSelectColumns(&$script)
    {
        $script .= "
    /**
     * Add all the columns needed to create a new object.
     *
     * Note: any columns that were marked with lazyLoad=\"true\" in the
     * XML schema will not be added to the select list and only loaded
     * on demand.
     *
     * @param Criteria \$criteria object containing the columns to add.
     * @param string   \$alias    optional table alias
     * @throws PropelException Any exceptions caught during processing will be
     *                         rethrown wrapped into a PropelException.
     */
    public static function addSelectColumns(Criteria \$criteria, \$alias = null)
    {
        if (null === \$alias) {";
        foreach ($this->getTable()->getColumns() as $col) {
            if (!$col->isLazyLoad()) {
                $script .= "
            \$criteria->addSelectColumn({$col->getFQConstantName()});";
            } // if !col->isLazyLoad
        } // foreach
        $script .= "
        } else {";
        foreach ($this->getTable()->getColumns() as $col) {
            if (!$col->isLazyLoad()) {
                $script .= "
            \$criteria->addSelectColumn(\$alias . '." . $col->getName()."');";
            } // if !col->isLazyLoad
        } // foreach
        $script .= "
        }";
        $script .="
    }
";
    } // addAddSelectColumns()

    /**
     * Adds the getTableMap() method which is a convenience method for apps to get DB metadata.
     * @param string &$script The script will be modified in this method.
     */
    protected function addGetTableMap(&$script)
    {
        $script .= "
    /**
     * Returns the TableMap related to this object.
     * This method is not needed for general use but a specific application could have a need.
     * @return TableMap
     * @throws PropelException Any exceptions caught during processing will be
     *                         rethrown wrapped into a PropelException.
     */
    public static function getTableMap()
    {
        return Propel::getServiceContainer()->getDatabaseMap(" . $this->getTableMapClass() . "::DATABASE_NAME)->getTable(" . $this->getTableMapClass() . "::TABLE_NAME);
    }
";
    }

    /**
     * Adds the doDeleteAll() method.
     * @param string &$script The script will be modified in this method.
     */
    protected function addDoDeleteAll(&$script)
    {
        $table = $this->getTable();
        $script .= "
    /**
     * Deletes all rows from the ".$table->getName()." table.
     *
     * @param ConnectionInterface \$con the connection to use
     * @return int The number of affected rows (if supported by underlying database driver).
     */
    public static function doDeleteAll(ConnectionInterface \$con = null)
    {
        return " . $this->getQueryClassName() . "::create()->doDeleteAll(\$con);
    }
";
    }

    /**
     * Adds the doDelete() method.
     * @param string &$script The script will be modified in this method.
     */
    protected function addDoDelete(&$script)
    {
        $table = $this->getTable();
        $script .= "
    /**
     * Performs a DELETE on the database, given a ".$this->getObjectClassName()." or Criteria object OR a primary key value.
     *
     * @param mixed               \$values Criteria or ".$this->getObjectClassName()." object or primary key or array of primary keys
     *              which is used to create the DELETE statement
     * @param  ConnectionInterface \$con the connection to use
     * @return int             The number of affected rows (if supported by underlying database driver).  This includes CASCADE-related rows
     *                         if supported by native driver or if emulated using Propel.
     * @throws PropelException Any exceptions caught during processing will be
     *                         rethrown wrapped into a PropelException.
     */
     public static function doDelete(\$values, ConnectionInterface \$con = null)
     {
        if (null === \$con) {
            \$con = Propel::getServiceContainer()->getWriteConnection(" . $this->getTableMapClass() . "::DATABASE_NAME);
        }

        if (\$values instanceof Criteria) {";
        $script .= "
            // rename for clarity
            \$criteria = \$values;
        } elseif (\$values instanceof \\".$this->getStubObjectBuilder()->getQualifiedClassName().") { // it's a model object";
        if (count($table->getPrimaryKey()) > 0) {
            $script .= "
            // create criteria based on pk values
            \$criteria = \$values->buildPkeyCriteria();";
        } else {
            $script .= "
            // create criteria based on pk value
            \$criteria = \$values->buildCriteria();";
        }

        $script .= "
        } else { // it's a primary key, or an array of pks";

        if (!$table->getPrimaryKey()) {
            $class = $this->getObjectName();
            $this->declareClass('Propel\\Runtime\\Exception\\LogicException');
            $script .= "
            throw new LogicException('The $class object has no primary key');";
        } else {
            $script .= "
            \$criteria = new Criteria(" . $this->getTableMapClass() . "::DATABASE_NAME);";

            if (1 === count($table->getPrimaryKey())) {
                $pkey = $table->getPrimaryKey();
                $col = array_shift($pkey);
                $script .= "
            \$criteria->add(".$this->getColumnConstant($col).", (array) \$values, Criteria::IN);";
            } else {
                $script .= "
            // primary key is composite; we therefore, expect
            // the primary key passed to be an array of pkey values
            if (count(\$values) == count(\$values, COUNT_RECURSIVE)) {
                // array is not multi-dimensional
                \$values = array(\$values);
            }
            foreach (\$values as \$value) {";
                $i = 0;
                foreach ($table->getPrimaryKey() as $col) {
                    if (0 === $i) {
                        $script .= "
                \$criterion = \$criteria->getNewCriterion(".$this->getColumnConstant($col).", \$value[$i]);";
                    } else {
                        $script .= "
                \$criterion->addAnd(\$criteria->getNewCriterion(".$this->getColumnConstant($col).", \$value[$i]));";
                    }
                    $i++;
                }
                $script .= "
                \$criteria->addOr(\$criterion);";
                $script .= "
            }";
            } /* if count(table->getPrimaryKeys()) */
        }

        $script .= "
        }

        \$query = " . $this->getQueryClassName() . "::create()->mergeWith(\$criteria);

        if (\$values instanceof Criteria) {
            {$this->getTableMapClassName()}::clearInstancePool();
        } elseif (!is_object(\$values)) { // it's a primary key, or an array of pks
            foreach ((array) \$values as \$singleval) {
                {$this->getTableMapClassName()}::removeInstanceFromPool(\$singleval);
            }
        }

        return \$query->delete(\$con);
    }
";
    }

    /**
     * Adds the doInsert() method.
     * @param string &$script The script will be modified in this method.
     */
    protected function addDoInsert(&$script)
    {
        $table = $this->getTable();
        $tableMapClass = $this->getTableMapClass();

        $script .= "
    /**
     * Performs an INSERT on the database, given a ".$this->getObjectClassName()." or Criteria object.
     *
     * @param mixed               \$criteria Criteria or ".$this->getObjectClassName()." object containing data that is used to create the INSERT statement.
     * @param ConnectionInterface \$con the ConnectionInterface connection to use
     * @return mixed           The new primary key.
     * @throws PropelException Any exceptions caught during processing will be
     *                         rethrown wrapped into a PropelException.
     */
    public static function doInsert(\$criteria, ConnectionInterface \$con = null)
    {
        if (null === \$con) {
            \$con = Propel::getServiceContainer()->getWriteConnection(" . $tableMapClass  . "::DATABASE_NAME);
        }

        if (\$criteria instanceof Criteria) {
            \$criteria = clone \$criteria; // rename for clarity
        } else {
            \$criteria = \$criteria->buildCriteria(); // build Criteria from ".$this->getObjectClassName()." object
        }
";

        foreach ($table->getColumns() as $col) {
            if ($col->isPrimaryKey()
                && $col->isAutoIncrement()
                && 'none' !== $table->getIdMethod()
                && !$table->isAllowPkInsert()
            ) {
                $script .= "
        if (\$criteria->containsKey(".$this->getColumnConstant($col).") && \$criteria->keyContainsValue(" . $this->getColumnConstant($col) . ") ) {
            throw new PropelException('Cannot insert a value for auto-increment primary key ('.".$this->getColumnConstant($col).".')');
        }
";
                if (!$this->getPlatform()->supportsInsertNullPk()) {
                    $script .= "
        // remove pkey col since this table uses auto-increment and passing a null value for it is not valid
        \$criteria->remove(".$this->getColumnConstant($col).");
";
                }
            } elseif ($col->isPrimaryKey()
                && $col->isAutoIncrement()
                && 'none' !== $table->getIdMethod()
                && $table->isAllowPkInsert()
                && !$this->getPlatform()->supportsInsertNullPk()
            ) {
                $script .= "
        // remove pkey col if it is null since this table does not accept that
        if (\$criteria->containsKey(".$this->getColumnConstant($col).") && !\$criteria->keyContainsValue(" . $this->getColumnConstant($col) . ") ) {
            \$criteria->remove(".$this->getColumnConstant($col).");
        }
";
            }
        }

        $script .= "

        // Set the correct dbName
        \$query = " . $this->getQueryClassName() . "::create()->mergeWith(\$criteria);

        // use transaction because \$criteria could contain info
        // for more than one table (I guess, conceivably)
        return \$con->transaction(function () use (\$con, \$query) {
            return \$query->doInsert(\$con);
        });
    }
";
    }

}