propelorm/Propel2

View on GitHub
src/Propel/Generator/Builder/Om/QueryBuilder.php
F

Remove call to debugging function var_export

                $value = var_export($rightValueOrColumn, true);
Severity: Minor
Found in src/Propel/Generator/Builder/Om/QueryBuilder.php - About 5 mins to fix

Remove call to debugging function var_export

                $leftValue = var_export($localValueOrColumn, true);
Severity: Minor
Found in src/Propel/Generator/Builder/Om/QueryBuilder.php - About 5 mins to fix

High overall complexity: 180

<?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 addFindPkSimple

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

        // this method is not needed if the table has no primary key

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 addFilterByCol

    protected function addFilterByCol(&$script, Column $col)
    {
        $colPhpName = $col->getPhpName();
        $colName = $col->getName();
        $variableName = $col->getCamelCaseName();

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 addFindPk

    protected function addFindPk(&$script)
    {
        $class = $this->getObjectClassName();
        $tableMapClassName = $this->getTableMapClassName();
        $table = $this->getTable();

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 addClassOpen

    protected function addClassOpen(&$script)
    {
        $table = $this->getTable();
        $tableName = $table->getName();
        $tableDesc = $table->getDescription();

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 addFilterByFk

    protected function addFilterByFk(&$script, $fk)
    {
        $this->declareClasses(
            '\Propel\Runtime\Collection\ObjectCollection',
            '\Propel\Runtime\Exception\PropelException'

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 addPrune

    protected function addPrune(&$script)
    {
        $table = $this->getTable();
        $class = $this->getObjectClassName();
        $objectName = '$' . $table->getCamelCaseName();

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 addFilterByRefFk

    protected function addFilterByRefFk(&$script, ForeignKey $fk)
    {
        $this->declareClasses(
            '\Propel\Runtime\Collection\ObjectCollection',
            '\Propel\Runtime\Exception\PropelException'

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 addDoOnDeleteCascade

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

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 addDoOnDeleteSetNull

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

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
Severity: Minor
Found in src/Propel/Generator/Builder/Om/QueryBuilder.php - About 1 wk to fix

Method addFilterByCol is too long

    protected function addFilterByCol(&$script, Column $col)
    {
        $colPhpName = $col->getPhpName();
        $colName = $col->getName();
        $variableName = $col->getCamelCaseName();
Severity: Minor
Found in src/Propel/Generator/Builder/Om/QueryBuilder.php - About 7 hrs to fix

Method addClassOpen is too long

    protected function addClassOpen(&$script)
    {
        $table = $this->getTable();
        $tableName = $table->getName();
        $tableDesc = $table->getDescription();
Severity: Minor
Found in src/Propel/Generator/Builder/Om/QueryBuilder.php - About 4 hrs to fix

Method addFindPkSimple is too long

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

        // this method is not needed if the table has no primary key
Severity: Minor
Found in src/Propel/Generator/Builder/Om/QueryBuilder.php - About 2 hrs to fix

Method addFindPk is too long

    protected function addFindPk(&$script)
    {
        $class = $this->getObjectClassName();
        $tableMapClassName = $this->getTableMapClassName();
        $table = $this->getTable();
Severity: Minor
Found in src/Propel/Generator/Builder/Om/QueryBuilder.php - About 1 hr to fix

Method addFilterByFk is too long

    protected function addFilterByFk(&$script, $fk)
    {
        $this->declareClasses(
            '\Propel\Runtime\Collection\ObjectCollection',
            '\Propel\Runtime\Exception\PropelException'
Severity: Minor
Found in src/Propel/Generator/Builder/Om/QueryBuilder.php - About 1 hr to fix

Cyclomatic complexity for function addFilterByCol is too high

    protected function addFilterByCol(&$script, Column $col)
    {
        $colPhpName = $col->getPhpName();
        $colName = $col->getName();
        $variableName = $col->getCamelCaseName();
Severity: Minor
Found in src/Propel/Generator/Builder/Om/QueryBuilder.php - About 1 hr to fix

Method addDoOnDeleteCascade is too long

    protected function addDoOnDeleteCascade(&$script)
    {
        $table = $this->getTable();
        $script .= "
    /**
Severity: Minor
Found in src/Propel/Generator/Builder/Om/QueryBuilder.php - About 1 hr to fix

Method addDoOnDeleteSetNull is too long

    protected function addDoOnDeleteSetNull(&$script)
    {
        $table = $this->getTable();
        $script .= "
    /**
Severity: Minor
Found in src/Propel/Generator/Builder/Om/QueryBuilder.php - About 1 hr to fix

Method addClassBody is too long

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

        // namespaces
Severity: Minor
Found in src/Propel/Generator/Builder/Om/QueryBuilder.php - About 1 hr to fix

Method addFilterByRefFk is too long

    protected function addFilterByRefFk(&$script, ForeignKey $fk)
    {
        $this->declareClasses(
            '\Propel\Runtime\Collection\ObjectCollection',
            '\Propel\Runtime\Exception\PropelException'
Severity: Minor
Found in src/Propel/Generator/Builder/Om/QueryBuilder.php - About 1 hr to fix

Method addFilterByPrimaryKeys is too long

    protected function addFilterByPrimaryKeys(&$script)
    {
        $script .= "
    /**
     * Filter the query by a list of primary keys
Severity: Minor
Found in src/Propel/Generator/Builder/Om/QueryBuilder.php - About 55 mins to fix

Method addDelete is too long

    protected function addDelete(&$script)
    {
        $script .= "
    /**
     * Performs a DELETE on the database based on the current ModelCriteria
Severity: Minor
Found in src/Propel/Generator/Builder/Om/QueryBuilder.php - About 45 mins to fix

Method addFindPks is too long

    protected function addFindPks(&$script)
    {
        $this->declareClasses(
            '\Propel\Runtime\Collection\ObjectCollection',
            '\Propel\Runtime\Connection\ConnectionInterface',
Severity: Minor
Found in src/Propel/Generator/Builder/Om/QueryBuilder.php - About 35 mins to fix

Too many parameters in definition of function addJoinRelated

    protected function addJoinRelated(&$script, $fkTable, $queryClass, $relationName, $joinType)
Severity: Minor
Found in src/Propel/Generator/Builder/Om/QueryBuilder.php - About 30 mins to fix

Too many parameters in definition of function addUseRelatedQuery

    protected function addUseRelatedQuery(&$script, Table $fkTable, $queryClass, $relationName, $joinType)
Severity: Minor
Found in src/Propel/Generator/Builder/Om/QueryBuilder.php - About 30 mins to fix

The variable name, joinedTableTableMapBuilder, is too long

            $joinedTableTableMapBuilder = $this->getNewTableMapBuilder($tblFK);
Severity: Minor
Found in src/Propel/Generator/Builder/Om/QueryBuilder.php - About 5 mins to fix

The variable name, refTableTableMapBuilder, is too long

            $refTableTableMapBuilder = $this->getNewTableMapBuilder($tblFK);
Severity: Minor
Found in src/Propel/Generator/Builder/Om/QueryBuilder.php - About 5 mins to fix

The variable name, pk, is too short

            $pk = $table->getPrimaryKey();
Severity: Minor
Found in src/Propel/Generator/Builder/Om/QueryBuilder.php - About 5 mins to fix

The variable name, i, is too short

            $i = 0;
Severity: Minor
Found in src/Propel/Generator/Builder/Om/QueryBuilder.php - About 5 mins to fix

Similar 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/QueryBuilder.php on lines 151..170

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

Similar 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/QueryBuilder.php on lines 130..149

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/QueryBuilder.php on lines 337..348

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/QueryBuilder.php on lines 355..366

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

Similar 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/QueryBuilder.php on lines 209..211

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

Similar 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/QueryBuilder.php on lines 187..189

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\Column;
use Propel\Generator\Model\CrossForeignKeys;
use Propel\Generator\Model\ForeignKey;
use Propel\Generator\Model\PropelTypes;
use Propel\Generator\Model\Table;

/**
 * Generates a PHP5 base Query class for user object model (OM).
 *
 * This class produces the base query class (e.g. BaseBookQuery) which contains
 * all the custom-built query methods.
 *
 * @author Francois Zaninotto
 */
class QueryBuilder extends AbstractOMBuilder
{
    /**
     * Returns the package for the [base] object classes.
     *
     * @return string
     */
    public function getPackage()
    {
        return parent::getPackage() . '.Base';
    }

    /**
     * Returns the namepace for the query object classes.
     *
     * @return string
     */
    public function getNamespace()
    {
        if ($namespace = parent::getNamespace()) {
                return $namespace . '\\Base';
        }

        return 'Base';
    }

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

    /**
     * Returns parent class name that extends TableQuery Object if is set this class must extends ModelCriteria for be compatible
     * @return string
     */
    public function getParentClass()
    {
        $parentClass = $this->getBehaviorContent('parentClass');
        return null === $parentClass ? ($this->getTable()->getBaseQueryClass() != "" ? $this->getTable()->getBaseQueryClass() : 'ModelCriteria') : $parentClass;
    }

    /**
     * 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();
        $tableName = $table->getName();
        $tableDesc = $table->getDescription();
        $queryClass = $this->getQueryClassName();
        $modelClass = $this->getObjectClassName();
        $parentClass = $this->getParentClass();
        $script .= "
/**
 * Base class that represents a query for the '$tableName' table.
 *
 * $tableDesc
 *";
        if ($this->getBuildProperty('generator.objectModel.addTimeStamp')) {
            $now = strftime('%c');
            $script .= "
 * This class was autogenerated by Propel " . $this->getBuildProperty('general.version') . " on:
 *
 * $now
 *";
        }

        // magic orderBy() methods, for IDE completion
        foreach ($this->getTable()->getColumns() as $column) {
            $script .= "
 * @method     $queryClass orderBy" . $column->getPhpName() . "(\$order = Criteria::ASC) Order by the " . $column->getName() . " column";
        }
        $script .= "
 *";

        // magic groupBy() methods, for IDE completion
        foreach ($this->getTable()->getColumns() as $column) {
            $script .= "
 * @method     $queryClass groupBy" . $column->getPhpName() . "() Group by the " . $column->getName() . " column";
        }

        // override the signature of ModelCriteria::left-, right- and innerJoin to specify the class of the returned object, for IDE completion
        $script .= "
 *
 * @method     $queryClass leftJoin(\$relation) Adds a LEFT JOIN clause to the query
 * @method     $queryClass rightJoin(\$relation) Adds a RIGHT JOIN clause to the query
 * @method     $queryClass innerJoin(\$relation) Adds a INNER JOIN clause to the query
 *";

        $script .= "
 * @method     $queryClass leftJoinWith(\$relation) Adds a LEFT JOIN clause and with to the query
 * @method     $queryClass rightJoinWith(\$relation) Adds a RIGHT JOIN clause and with to the query
 * @method     $queryClass innerJoinWith(\$relation) Adds a INNER JOIN clause and with to the query
 *";

        $relationQueryClasses = [];

        // magic XXXjoinYYY() methods, for IDE completion
        foreach ($this->getTable()->getForeignKeys() as $fk) {
            $relationName = $this->getFKPhpNameAffix($fk);

            $script .= "
 * @method     $queryClass leftJoin" . $relationName . "(\$relationAlias = null) Adds a LEFT JOIN clause to the query using the " . $relationName . " relation
 * @method     $queryClass rightJoin" . $relationName . "(\$relationAlias = null) Adds a RIGHT JOIN clause to the query using the " . $relationName . " relation
 * @method     $queryClass innerJoin" . $relationName . "(\$relationAlias = null) Adds a INNER JOIN clause to the query using the " . $relationName . " relation
 *";

            $script .= "
 * @method     $queryClass joinWith" . $relationName . "(\$joinType = Criteria::INNER_JOIN) Adds a join clause and with to the query using the " . $relationName . " relation
 *";

            $script .= "
 * @method     $queryClass leftJoinWith" . $relationName . "() Adds a LEFT JOIN clause and with to the query using the " . $relationName . " relation
 * @method     $queryClass rightJoinWith" . $relationName . "() Adds a RIGHT JOIN clause and with to the query using the " . $relationName . " relation
 * @method     $queryClass innerJoinWith" . $relationName . "() Adds a INNER JOIN clause and with to the query using the " . $relationName . " relation
 *";

            $relationQueryClasses[$this->getNewStubQueryBuilder($fk->getForeignTable())->getQueryClassName(true)] = true;
        }
        foreach ($this->getTable()->getReferrers() as $refFK) {
            $relationName = $this->getRefFKPhpNameAffix($refFK);

            $script .= "
 * @method     $queryClass leftJoin" . $relationName . "(\$relationAlias = null) Adds a LEFT JOIN clause to the query using the " . $relationName . " relation
 * @method     $queryClass rightJoin" . $relationName . "(\$relationAlias = null) Adds a RIGHT JOIN clause to the query using the " . $relationName . " relation
 * @method     $queryClass innerJoin" . $relationName . "(\$relationAlias = null) Adds a INNER JOIN clause to the query using the " . $relationName . " relation
 *";

            $script .= "
 * @method     $queryClass joinWith" . $relationName . "(\$joinType = Criteria::INNER_JOIN) Adds a join clause and with to the query using the " . $relationName . " relation
 *";

            $script .= "
 * @method     $queryClass leftJoinWith" . $relationName . "() Adds a LEFT JOIN clause and with to the query using the " . $relationName . " relation
 * @method     $queryClass rightJoinWith" . $relationName . "() Adds a RIGHT JOIN clause and with to the query using the " . $relationName . " relation
 * @method     $queryClass innerJoinWith" . $relationName . "() Adds a INNER JOIN clause and with to the query using the " . $relationName . " relation
 *";

            $relationQueryClasses[$this->getNewStubQueryBuilder($refFK->getTable())->getQueryClassName(true)] = true;
        }

        if (!empty($relationQueryClasses)) {
            $relationQueryClasses = implode('|', array_keys($relationQueryClasses));
            $script .= "
 * @method     $relationQueryClasses endUse() Finalizes a secondary criteria and merges it with its primary Criteria
 *";
        }

        // override the signature of ModelCriteria::findOne() to specify the class of the returned object, for IDE completion
        $script .= "
 * @method     $modelClass findOne(ConnectionInterface \$con = null) Return the first $modelClass matching the query
 * @method     $modelClass findOneOrCreate(ConnectionInterface \$con = null) Return the first $modelClass matching the query, or a new $modelClass object populated from the query conditions when no match is found
 *";

        // magic findBy() methods, for IDE completion
        foreach ($this->getTable()->getColumns() as $column) {
            $script .= "
 * @method     $modelClass findOneBy" . $column->getPhpName() . "(" . $column->getPhpType() . " \$" . $column->getName() . ") Return the first $modelClass filtered by the " . $column->getName() . " column";
        }

        $script .= " * \n";

        // override the signature of ModelCriteria::require*() to specify the class of the returned object, for IDE completion
        $script .= "
 * @method     $modelClass requirePk(\$key, ConnectionInterface \$con = null) Return the $modelClass by primary key and throws {$this->getEntityNotFoundExceptionClass()} when not found
 * @method     $modelClass requireOne(ConnectionInterface \$con = null) Return the first $modelClass matching the query and throws {$this->getEntityNotFoundExceptionClass()} when not found
 *";

        // magic requireOneBy() methods, for IDE completion
        foreach ($this->getTable()->getColumns() as $column) {
            $script .= "
 * @method     $modelClass requireOneBy" . $column->getPhpName() . "(" . $column->getPhpType() . " \$" . $column->getName() . ") Return the first $modelClass filtered by the " . $column->getName() . " column and throws {$this->getEntityNotFoundExceptionClass()} when not found";
        }

        $script .= "
 *
 * @method     {$modelClass}[]|ObjectCollection find(ConnectionInterface \$con = null) Return $modelClass objects based on current ModelCriteria";
        foreach ($this->getTable()->getColumns() as $column) {
            $script .= "
 * @method     {$modelClass}[]|ObjectCollection findBy" . $column->getPhpName() . "(" . $column->getPhpType() . " \$" . $column->getName() . ") Return $modelClass objects filtered by the " . $column->getName() . " column";
        }

        $script .= "
 * @method     {$modelClass}[]|\\Propel\\Runtime\\Util\\PropelModelPager paginate(\$page = 1, \$maxPerPage = 10, ConnectionInterface \$con = null) Issue a SELECT query based on the current ModelCriteria and uses a page and a maximum number of results per page to compute an offset and a limit
 *
 */
abstract class ".$this->getUnqualifiedClassName()." extends " . $parentClass . "
{
    ";
    }

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

        // namespaces
        $this->declareClasses(
            '\Propel\Runtime\Propel',
            '\Propel\Runtime\ActiveQuery\ModelCriteria',
            '\Propel\Runtime\ActiveQuery\Criteria',
            '\Propel\Runtime\ActiveQuery\ModelJoin',
            '\Exception',
            '\Propel\Runtime\Exception\PropelException'
        );
        $this->declareClassFromBuilder($this->getStubQueryBuilder(), 'Child');
        $this->declareClassFromBuilder($this->getTableMapBuilder());

        // apply behaviors
        $this->applyBehaviorModifier('queryAttributes', $script, "    ");
        $this->addEntityNotFoundExceptionClass($script);
        $this->addConstructor($script);
        $this->addFactory($script);
        $this->addFindPk($script);
        $this->addFindPkSimple($script);
        $this->addFindPkComplex($script);
        $this->addFindPks($script);
        $this->addFilterByPrimaryKey($script);
        $this->addFilterByPrimaryKeys($script);
        foreach ($this->getTable()->getColumns() as $col) {
            $this->addFilterByCol($script, $col);
            if ($col->isNamePlural()) {
                if ($col->getType() === PropelTypes::PHP_ARRAY) {
                    $this->addFilterByArrayCol($script, $col);
                } elseif ($col->isSetType()) {
                    $this->addFilterBySetCol($script, $col);
                }
            }

        }
        foreach ($this->getTable()->getForeignKeys() as $fk) {
            $this->addFilterByFK($script, $fk);
            $this->addJoinFk($script, $fk);
            $this->addUseFKQuery($script, $fk);
        }
        foreach ($this->getTable()->getReferrers() as $refFK) {
            $this->addFilterByRefFK($script, $refFK);
            $this->addJoinRefFk($script, $refFK);
            $this->addUseRefFKQuery($script, $refFK);
        }
        foreach ($this->getTable()->getCrossFks() as $crossFKs) {
            $this->addFilterByCrossFK($script, $crossFKs);
        }
        $this->addPrune($script);
        $this->addBasePreSelect($script);
        $this->addBasePreDelete($script);
        $this->addBasePostDelete($script);
        $this->addBasePreUpdate($script);
        $this->addBasePostUpdate($script);

        // add the insert, update, delete, etc. methods
        if (!$table->isAlias() && !$table->isReadOnly()) {
            $this->addDeleteMethods($script);
        }

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

    /**
     * Adds the entityNotFoundExceptionClass property which is necessary for the `requireOne` method
     * of the `ModelCriteria`
     */
    protected function addEntityNotFoundExceptionClass(&$script)
    {
        $script .= "protected \$entityNotFoundExceptionClass = '" . addslashes($this->getEntityNotFoundExceptionClass()) . "';\n";
    }

    private function getEntityNotFoundExceptionClass()
    {
        return $this->getBuildProperty('generator.objectModel.entityNotFoundExceptionClass');
    }

    /**
     * Adds the doDeleteAll(), etc. methods.
     * @param string &$script The script will be modified in this method.
     */
    protected function addDeleteMethods(&$script)
    {
        $this->addDoDeleteAll($script);
        $this->addDelete($script);

        if ($this->isDeleteCascadeEmulationNeeded()) {
            $this->addDoOnDeleteCascade($script);
        }

        if ($this->isDeleteSetNullEmulationNeeded()) {
            $this->addDoOnDeleteSetNull($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('generator.objectModel.emulateForeignKeyConstraints')) && count($table->getReferrers()) > 0) {
            foreach ($table->getReferrers() as $fk) {
                if ( ForeignKey::CASCADE === $fk->getOnDelete()) {
                    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('generator.objectModel.emulateForeignKeyConstraints')) && count($table->getReferrers()) > 0) {
            foreach ($table->getReferrers() as $fk) {
                if (ForeignKey::SETNULL === $fk->getOnDelete()) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Closes class.
     * @param string &$script The script will be modified in this method.
     */
    protected function addClassClose(&$script)
    {
        $script .= "
} // " . $this->getUnqualifiedClassName() . "
";
        $this->applyBehaviorModifier('queryFilter', $script, "");
    }

    /**
     * Adds the constructor for this object.
     * @param string &$script The script will be modified in this method.
     * @see addConstructor()
     */
    protected function addConstructor(&$script)
    {
        $this->addConstructorComment($script);
        $this->addConstructorOpen($script);
        $this->addConstructorBody($script);
        $this->addConstructorClose($script);
    }

    /**
     * Adds the comment for the constructor
     * @param string &$script The script will be modified in this method.
     **/
    protected function addConstructorComment(&$script)
    {
        $script .= "
    /**
     * Initializes internal state of ".$this->getClassName()." object.
     *
     * @param     string \$dbName The database name
     * @param     string \$modelName The phpName of a model, e.g. 'Book'
     * @param     string \$modelAlias The alias for the model in this query, e.g. 'b'
     */";
    }

    /**
     * Adds the function declaration for the constructor
     * @param string &$script The script will be modified in this method.
     **/
    protected function addConstructorOpen(&$script)
    {
        $table = $this->getTable();
        $script .= "
    public function __construct(\$dbName = '" . $table->getDatabase()->getName() . "', \$modelName = '" . addslashes($this->getNewStubObjectBuilder($table)->getFullyQualifiedClassName()) . "', \$modelAlias = null)
    {";
    }

    /**
     * Adds the function body for the constructor
     * @param string &$script The script will be modified in this method.
     **/
    protected function addConstructorBody(&$script)
    {
        $script .= "
        parent::__construct(\$dbName, \$modelName, \$modelAlias);";
    }

    /**
     * Adds the function close for the constructor
     * @param string &$script The script will be modified in this method.
     **/
    protected function addConstructorClose(&$script)
    {
        $script .= "
    }
";
    }

    /**
     * Adds the factory for this object.
     * @param string &$script The script will be modified in this method.
     */
    protected function addFactory(&$script)
    {
        $this->addFactoryComment($script);
        $this->addFactoryOpen($script);
        $this->addFactoryBody($script);
        $this->addFactoryClose($script);
    }

    /**
     * Adds the comment for the factory
     * @param string &$script The script will be modified in this method.
     **/
    protected function addFactoryComment(&$script)
    {
        $classname = $this->getClassNameFromBuilder($this->getNewStubQueryBuilder($this->getTable()));
        $script .= "
    /**
     * Returns a new " . $classname . " object.
     *
     * @param     string \$modelAlias The alias of a model in the query
     * @param     Criteria \$criteria Optional Criteria to build the query from
     *
     * @return " . $classname . "
     */";
    }

    /**
     * Adds the function declaration for the factory
     * @param string &$script The script will be modified in this method.
     **/
    protected function addFactoryOpen(&$script)
    {
        $script .= "
    public static function create(\$modelAlias = null, Criteria \$criteria = null)
    {";
    }

    /**
     * Adds the function body for the factory
     * @param string &$script The script will be modified in this method.
     */
    protected function addFactoryBody(&$script)
    {
        $classname = $this->getClassNameFromBuilder($this->getNewStubQueryBuilder($this->getTable()));
        $script .= "
        if (\$criteria instanceof " . $classname . ") {
            return \$criteria;
        }
        \$query = new " . $classname . "();
        if (null !== \$modelAlias) {
            \$query->setModelAlias(\$modelAlias);
        }
        if (\$criteria instanceof Criteria) {
            \$query->mergeWith(\$criteria);
        }

        return \$query;";
    }

    /**
     * Adds the function close for the factory
     * @param string &$script The script will be modified in this method.
     */
    protected function addFactoryClose(&$script)
    {
        $script .= "
    }
";
    }

    protected function addFindPk(&$script)
    {
        $class = $this->getObjectClassName();
        $tableMapClassName = $this->getTableMapClassName();
        $table = $this->getTable();

        $script .= "
    /**
     * Find object by primary key.
     * Propel uses the instance pool to skip the database if the object exists.
     * Go fast if the query is untouched.
     *";
        if ($table->hasCompositePrimaryKey()) {
            $pks = $table->getPrimaryKey();
            $examplePk = array_slice([12, 34, 56, 78, 91], 0, count($pks));
            $colNames = [];
            foreach ($pks as $col) {
                $colNames[]= '$' . $col->getName();
            }
            $pkType = 'array['. join($colNames, ', ') . ']';
            $script .= "
     * <code>
     * \$obj = \$c->findPk(array(" . join($examplePk, ', ') . "), \$con);";
        } else {
            $pkType = 'mixed';
            $script .= "
     * <code>
     * \$obj  = \$c->findPk(12, \$con);";
        }
        $script .= "
     * </code>
     *
     * @param " . $pkType . " \$key Primary key to use for the query
     * @param ConnectionInterface \$con an optional connection object
     *
     * @return $class|array|mixed the result, formatted by the current formatter
     */
    public function findPk(\$key, ConnectionInterface \$con = null)
    {";
        if (!$table->hasPrimaryKey()) {
            $this->declareClass('Propel\\Runtime\\Exception\\LogicException');
            $script .= "
        throw new LogicException('The {$this->getObjectName()} object has no primary key');
    }
";

            return $script;
        }

        $script .= "
        if (\$key === null) {
            return null;
        }";
        if ($table->hasCompositePrimaryKey()) {
            $pks = [];
            foreach ($table->getPrimaryKey() as $index => $column) {
                $pks[] = "\$key[$index]";
            }
        } else {
            $pks = '$key';
        }
        $pkHash = $this->getTableMapBuilder()->getInstancePoolKeySnippet($pks);
        $script .= "

        if (\$con === null) {
            \$con = Propel::getServiceContainer()->getReadConnection({$this->getTableMapClass()}::DATABASE_NAME);
        }

        \$this->basePreSelect(\$con);

        if (
            \$this->formatter || \$this->modelAlias || \$this->with || \$this->select
            || \$this->selectColumns || \$this->asColumns || \$this->selectModifiers
            || \$this->map || \$this->having || \$this->joins
        ) {
            return \$this->findPkComplex(\$key, \$con);
        }

        if ((null !== (\$obj = {$tableMapClassName}::getInstanceFromPool({$pkHash})))) {
            // the object is already in the instance pool
            return \$obj;
        }

        return \$this->findPkSimple(\$key, \$con);
    }
";
    }

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

        // this method is not needed if the table has no primary key
        if (!$table->hasPrimaryKey()) {
            return '';
        }

        $platform = $this->getPlatform();
        $tableMapClassName = $this->getTableMapClassName();
        $ARClassName = $this->getObjectClassName();
        $this->declareClassFromBuilder($this->getStubObjectBuilder());
        $this->declareClasses('\PDO');
        $selectColumns = [];
        foreach ($table->getColumns() as $column) {
            if (!$column->isLazyLoad()) {
                $selectColumns []= $this->quoteIdentifier($column->getName());
            }
        }
        $conditions = [];
        foreach ($table->getPrimaryKey() as $index => $column) {
            $conditions []= sprintf('%s = :p%d', $this->quoteIdentifier($column->getName()), $index);
        }
        $query = sprintf(
            'SELECT %s FROM %s WHERE %s',
            implode(', ', $selectColumns),
            $this->quoteIdentifier($table->getName()),
            implode(' AND ', $conditions)
        );
        $pks = [];
        if ($table->hasCompositePrimaryKey()) {
            foreach ($table->getPrimaryKey() as $index => $column) {
                $pks []= "\$key[$index]";
            }
        } else {
            $pks []= "\$key";
        }

        $pkHashFromRow = $this->getTableMapBuilder()->getInstancePoolKeySnippet($pks);
        $script .= "
    /**
     * Find object by primary key using raw SQL to go fast.
     * Bypass doSelect() and the object formatter by using generated code.
     *
     * @param     mixed \$key Primary key to use for the query
     * @param     ConnectionInterface \$con A connection object
     *
     * @throws \\Propel\\Runtime\\Exception\\PropelException
     *
     * @return $ARClassName A model object, or null if the key is not found
     */
    protected function findPkSimple(\$key, ConnectionInterface \$con)
    {
        \$sql = '$query';
        try {
            \$stmt = \$con->prepare(\$sql);";
        if ($table->hasCompositePrimaryKey()) {
            foreach ($table->getPrimaryKey() as $index => $column) {
                $script .= $platform->getColumnBindingPHP($column, "':p$index'", "\$key[$index]", '            ');
            }
        } else {
            $pk = $table->getPrimaryKey();
            $column = $pk[0];
            $script .= $platform->getColumnBindingPHP($column, "':p0'", "\$key", '            ');
        }
        $script .= "
            \$stmt->execute();
        } catch (Exception \$e) {
            Propel::log(\$e->getMessage(), Propel::LOG_ERR);
            throw new PropelException(sprintf('Unable to execute SELECT statement [%s]', \$sql), 0, \$e);
        }
        \$obj = null;
        if (\$row = \$stmt->fetch(\PDO::FETCH_NUM)) {";

        if ($table->getChildrenColumn()) {
            $script .="
            \$cls = {$tableMapClassName}::getOMClass(\$row, 0, false);
            /** @var $ARClassName \$obj */
            \$obj = new \$cls();";
        } else {
            $script .="
            /** @var $ARClassName \$obj */
            \$obj = new $ARClassName();";
        }
        $script .= "
            \$obj->hydrate(\$row);
            {$tableMapClassName}::addInstanceToPool(\$obj, $pkHashFromRow);
        }
        \$stmt->closeCursor();

        return \$obj;
    }
";
    }

    /**
     * Adds the findPk method for this object.
     * @param string &$script The script will be modified in this method.
     */
    protected function addFindPkComplex(&$script)
    {
        $class = $this->getObjectClassName();
        $table = $this->getTable();

        // this method is not needed if the table has no primary key
        if (!$table->hasPrimaryKey()) {
            return '';
        }

        $this->declareClasses('\Propel\Runtime\Connection\ConnectionInterface');
        $script .= "
    /**
     * Find object by primary key.
     *
     * @param     mixed \$key Primary key to use for the query
     * @param     ConnectionInterface \$con A connection object
     *
     * @return " . $class . "|array|mixed the result, formatted by the current formatter
     */
    protected function findPkComplex(\$key, ConnectionInterface \$con)
    {
        // As the query uses a PK condition, no limit(1) is necessary.
        \$criteria = \$this->isKeepQuery() ? clone \$this : \$this;
        \$dataFetcher = \$criteria
            ->filterByPrimaryKey(\$key)
            ->doSelect(\$con);

        return \$criteria->getFormatter()->init(\$criteria)->formatOne(\$dataFetcher);
    }
";
    }

    /**
     * Adds the findPks method for this object.
     * @param string &$script The script will be modified in this method.
     */
    protected function addFindPks(&$script)
    {
        $this->declareClasses(
            '\Propel\Runtime\Collection\ObjectCollection',
            '\Propel\Runtime\Connection\ConnectionInterface',
            '\Propel\Runtime\Propel'
        );
        $table = $this->getTable();
        $pks = $table->getPrimaryKey();
        $count = count($pks);
        $script .= "
    /**
     * Find objects by primary key
     * <code>";
        if (1 === $count) {
            $script .= "
     * \$objs = \$c->findPks(array(12, 56, 832), \$con);";
        } else {
            $script .= "
     * \$objs = \$c->findPks(array(array(12, 56), array(832, 123), array(123, 456)), \$con);";
        }
        $script .= "
     * </code>
     * @param     array \$keys Primary keys to use for the query
     * @param     ConnectionInterface \$con an optional connection object
     *
     * @return ObjectCollection|array|mixed the list of results, formatted by the current formatter
     */
    public function findPks(\$keys, ConnectionInterface \$con = null)
    {";
        if (!$table->hasPrimaryKey()) {
            $this->declareClass('Propel\\Runtime\\Exception\\LogicException');
            $script .= "
        throw new LogicException('The {$this->getObjectName()} object has no primary key');
    }
";

            return $script;
        }

        $script .= "
        if (null === \$con) {
            \$con = Propel::getServiceContainer()->getReadConnection(\$this->getDbName());
        }
        \$this->basePreSelect(\$con);
        \$criteria = \$this->isKeepQuery() ? clone \$this : \$this;
        \$dataFetcher = \$criteria
            ->filterByPrimaryKeys(\$keys)
            ->doSelect(\$con);

        return \$criteria->getFormatter()->init(\$criteria)->format(\$dataFetcher);
    }
";
    }

    /**
     * Adds the filterByPrimaryKey method for this object.
     * @param string &$script The script will be modified in this method.
     */
    protected function addFilterByPrimaryKey(&$script)
    {
        $script .= "
    /**
     * Filter the query by primary key
     *
     * @param     mixed \$key Primary key to use for the query
     *
     * @return \$this|" . $this->getQueryClassName() . " The current query, for fluid interface
     */
    public function filterByPrimaryKey(\$key)
    {";
        $table = $this->getTable();

        if (!$table->hasPrimaryKey()) {
            $this->declareClass('Propel\\Runtime\\Exception\\LogicException');
            $script .= "
        throw new LogicException('The {$this->getObjectName()} object has no primary key');
    }
";

            return $script;
        }

        $pks = $table->getPrimaryKey();
        if (1 === count($pks)) {
            // simple primary key
            $col = $pks[0];
            $const = $this->getColumnConstant($col);
            $script .= "

        return \$this->addUsingAlias($const, \$key, Criteria::EQUAL);";
        } else {
            // composite primary key
            $i = 0;
            foreach ($pks as $col) {
                $const = $this->getColumnConstant($col);
                $script .= "
        \$this->addUsingAlias($const, \$key[$i], Criteria::EQUAL);";
                $i++;
            }
            $script .= "

        return \$this;";
        }
        $script .= "
    }
";
    }

    /**
     * Adds the filterByPrimaryKey method for this object.
     * @param string &$script The script will be modified in this method.
     */
    protected function addFilterByPrimaryKeys(&$script)
    {
        $script .= "
    /**
     * Filter the query by a list of primary keys
     *
     * @param     array \$keys The list of primary key to use for the query
     *
     * @return \$this|" . $this->getQueryClassName() . " The current query, for fluid interface
     */
    public function filterByPrimaryKeys(\$keys)
    {";
        $table = $this->getTable();

        if (!$table->hasPrimaryKey()) {

            $this->declareClass('Propel\\Runtime\\Exception\\LogicException');
            $script .= "
        throw new LogicException('The {$this->getObjectName()} object has no primary key');
    }
";

            return $script;
        }

        $pks = $table->getPrimaryKey();
        if (1 === count($pks)) {
            // simple primary key
            $col = $pks[0];
            $const = $this->getColumnConstant($col);
            $script .= "

        return \$this->addUsingAlias($const, \$keys, Criteria::IN);";
        } else {
            // composite primary key
            $script .= "
        if (empty(\$keys)) {
            return \$this->add(null, '1<>1', Criteria::CUSTOM);
        }
        foreach (\$keys as \$key) {";
            $i = 0;
            foreach ($pks as $col) {
                $const = $this->getColumnConstant($col);
                $script .= "
            \$cton$i = \$this->getNewCriterion($const, \$key[$i], Criteria::EQUAL);";
                if ($i > 0) {
                    $script .= "
            \$cton0->addAnd(\$cton$i);";
                }
                $i++;
            }
            $script .= "
            \$this->addOr(\$cton0);
        }";
            $script .= "

        return \$this;";
        }
        $script .= "
    }
";
    }

    /**
     * Adds the filterByCol method for this object.
     * @param string &$script The script will be modified in this method.
     * @param Column $col
     */
    protected function addFilterByCol(&$script, Column $col)
    {
        $colPhpName = $col->getPhpName();
        $colName = $col->getName();
        $variableName = $col->getCamelCaseName();
        $qualifiedName = $this->getColumnConstant($col);
        $script .= "
    /**
     * Filter the query on the $colName column
     *";
        if ($col->isNumericType()) {
            $script .= "
     * Example usage:
     * <code>
     * \$query->filterBy$colPhpName(1234); // WHERE $colName = 1234
     * \$query->filterBy$colPhpName(array(12, 34)); // WHERE $colName IN (12, 34)
     * \$query->filterBy$colPhpName(array('min' => 12)); // WHERE $colName > 12
     * </code>";
            if ($col->isForeignKey()) {
                foreach ($col->getForeignKeys() as $fk) {
                    $script .= "
     *
     * @see       filterBy" . $this->getFKPhpNameAffix($fk) . "()";
                }
            }
            $script .= "
     *
     * @param     mixed \$$variableName The value to use as filter.
     *              Use scalar values for equality.
     *              Use array values for in_array() equivalent.
     *              Use associative array('min' => \$minValue, 'max' => \$maxValue) for intervals.";
        } elseif ($col->isTemporalType()) {
            $script .= "
     * Example usage:
     * <code>
     * \$query->filterBy$colPhpName('2011-03-14'); // WHERE $colName = '2011-03-14'
     * \$query->filterBy$colPhpName('now'); // WHERE $colName = '2011-03-14'
     * \$query->filterBy$colPhpName(array('max' => 'yesterday')); // WHERE $colName > '2011-03-13'
     * </code>
     *
     * @param     mixed \$$variableName The value to use as filter.
     *              Values can be integers (unix timestamps), DateTime objects, or strings.
     *              Empty strings are treated as NULL.
     *              Use scalar values for equality.
     *              Use array values for in_array() equivalent.
     *              Use associative array('min' => \$minValue, 'max' => \$maxValue) for intervals.";
        } elseif ($col->getType() == PropelTypes::PHP_ARRAY) {
            $script .= "
     * @param     array \$$variableName The values to use as filter.";
        } elseif ($col->isTextType()) {
            $script .= "
     * Example usage:
     * <code>
     * \$query->filterBy$colPhpName('fooValue');   // WHERE $colName = 'fooValue'
     * \$query->filterBy$colPhpName('%fooValue%', Criteria::LIKE); // WHERE $colName LIKE '%fooValue%'
     * </code>
     *
     * @param     string \$$variableName The value to use as filter.";
        } elseif ($col->isBooleanType()) {
            $script .= "
     * Example usage:
     * <code>
     * \$query->filterBy$colPhpName(true); // WHERE $colName = true
     * \$query->filterBy$colPhpName('yes'); // WHERE $colName = true
     * </code>
     *
     * @param     boolean|string \$$variableName The value to use as filter.
     *              Non-boolean arguments are converted using the following rules:
     *                * 1, '1', 'true',  'on',  and 'yes' are converted to boolean true
     *                * 0, '0', 'false', 'off', and 'no'  are converted to boolean false
     *              Check on string values is case insensitive (so 'FaLsE' is seen as 'false').";
        } else {
            $script .= "
     * @param     mixed \$$variableName The value to use as filter";
        }
        $script .= "
     * @param     string \$comparison Operator to use for the column comparison, defaults to Criteria::EQUAL
     *
     * @return \$this|" . $this->getQueryClassName() . " The current query, for fluid interface
     */
    public function filterBy$colPhpName(\$$variableName = null, \$comparison = null)
    {";
        if ($col->isNumericType() || $col->isTemporalType()) {
            $script .= "
        if (is_array(\$$variableName)) {
            \$useMinMax = false;
            if (isset(\${$variableName}['min'])) {
                \$this->addUsingAlias($qualifiedName, \${$variableName}['min'], Criteria::GREATER_EQUAL);
                \$useMinMax = true;
            }
            if (isset(\${$variableName}['max'])) {
                \$this->addUsingAlias($qualifiedName, \${$variableName}['max'], Criteria::LESS_EQUAL);
                \$useMinMax = true;
            }
            if (\$useMinMax) {
                return \$this;
            }
            if (null === \$comparison) {
                \$comparison = Criteria::IN;
            }
        }";
        } elseif ($col->getType() == PropelTypes::OBJECT) {
            $script .= "
        if (is_object(\$$variableName)) {
            \$$variableName = serialize(\$$variableName);
        }";
        } elseif ($col->getType() == PropelTypes::PHP_ARRAY) {
            $script .= "
        \$key = \$this->getAliasedColName($qualifiedName);
        if (null === \$comparison || \$comparison == Criteria::CONTAINS_ALL) {
            foreach (\$$variableName as \$value) {
                \$value = '%| ' . \$value . ' |%';
                if (\$this->containsKey(\$key)) {
                    \$this->addAnd(\$key, \$value, Criteria::LIKE);
                } else {
                    \$this->add(\$key, \$value, Criteria::LIKE);
                }
            }

            return \$this;
        } elseif (\$comparison == Criteria::CONTAINS_SOME) {
            foreach (\$$variableName as \$value) {
                \$value = '%| ' . \$value . ' |%';
                if (\$this->containsKey(\$key)) {
                    \$this->addOr(\$key, \$value, Criteria::LIKE);
                } else {
                    \$this->add(\$key, \$value, Criteria::LIKE);
                }
            }

            return \$this;
        } elseif (\$comparison == Criteria::CONTAINS_NONE) {
            foreach (\$$variableName as \$value) {
                \$value = '%| ' . \$value . ' |%';
                if (\$this->containsKey(\$key)) {
                    \$this->addAnd(\$key, \$value, Criteria::NOT_LIKE);
                } else {
                    \$this->add(\$key, \$value, Criteria::NOT_LIKE);
                }
            }
            \$this->addOr(\$key, null, Criteria::ISNULL);

            return \$this;
        }";
        } elseif ($col->isSetType()) {
            $this->declareClasses(
                'Propel\Common\Util\SetColumnConverter',
                'Propel\Common\Exception\SetColumnConverterException'
            );
            $script .= "
        \$valueSet = " . $this->getTableMapClassName() . "::getValueSet(" . $this->getColumnConstant($col) . ");
        try {
            \${$variableName} = SetColumnConverter::convertToInt(\${$variableName}, \$valueSet);
        } catch (SetColumnConverterException \$e) {
            throw new PropelException(sprintf('Value \"%s\" is not accepted in this set column', \$e->getValue()), \$e->getCode(), \$e);
        }
        if (null === \$comparison || \$comparison == Criteria::CONTAINS_ALL) {
            if (\${$variableName} === '0') {
                return \$this;
            }
            \$comparison = Criteria::BINARY_ALL;
        } elseif (\$comparison == Criteria::CONTAINS_SOME || \$comparison == Criteria::IN) {
            if (\${$variableName} === '0') {
                return \$this;
            }
            \$comparison = Criteria::BINARY_AND;
        } elseif (\$comparison == Criteria::CONTAINS_NONE) {
            \$key = \$this->getAliasedColName($qualifiedName);
            if (\${$variableName} !== '0') {
                \$this->add(\$key, \${$variableName}, Criteria::BINARY_NONE);
            }
            \$this->addOr(\$key, null, Criteria::ISNULL);
            
            return \$this;
        }";
        } elseif ($col->getType() == PropelTypes::ENUM) {
            $script .= "
        \$valueSet = " . $this->getTableMapClassName() . "::getValueSet(" . $this->getColumnConstant($col) . ");
        if (is_scalar(\$$variableName)) {
            if (!in_array(\$$variableName, \$valueSet)) {
                throw new PropelException(sprintf('Value \"%s\" is not accepted in this enumerated column', \$$variableName));
            }
            \$$variableName = array_search(\$$variableName, \$valueSet);
        } elseif (is_array(\$$variableName)) {
            \$convertedValues = array();
            foreach (\$$variableName as \$value) {
                if (!in_array(\$value, \$valueSet)) {
                    throw new PropelException(sprintf('Value \"%s\" is not accepted in this enumerated column', \$value));
                }
                \$convertedValues []= array_search(\$value, \$valueSet);
            }
            \$$variableName = \$convertedValues;
            if (null === \$comparison) {
                \$comparison = Criteria::IN;
            }
        }";
        } elseif ($col->isTextType()) {
            $script .= "
        if (null === \$comparison) {
            if (is_array(\$$variableName)) {
                \$comparison = Criteria::IN;
            }
        }";
        } elseif ($col->isBooleanType()) {
            $script .= "
        if (is_string(\$$variableName)) {
            \$$variableName = in_array(strtolower(\$$variableName), array('false', 'off', '-', 'no', 'n', '0', '')) ? false : true;
        }";
        }
        $script .= "

        return \$this->addUsingAlias($qualifiedName, \$$variableName, \$comparison);
    }
";
    }

    /**
     * Adds the singular filterByCol method for an Array column.
     * @param string &$script The script will be modified in this method.
     * @param Column $col
     */
    protected function addFilterByArrayCol(&$script, Column $col)
    {
        $colPhpName = $col->getPhpName();
        $singularPhpName = $col->getPhpSingularName();
        $colName = $col->getName();
        $variableName = $col->getCamelCaseName();
        $qualifiedName = $this->getColumnConstant($col);
        $script .= "
    /**
     * Filter the query on the $colName column
     * @param     mixed \$$variableName The value to use as filter
     * @param     string \$comparison Operator to use for the column comparison, defaults to Criteria::CONTAINS_ALL
     *
     * @return \$this|" . $this->getQueryClassName() . " The current query, for fluid interface
     */
    public function filterBy$singularPhpName(\$$variableName = null, \$comparison = null)
    {
        if (null === \$comparison || \$comparison == Criteria::CONTAINS_ALL) {
            if (is_scalar(\$$variableName)) {
                \$$variableName = '%| ' . \$$variableName . ' |%';
                \$comparison = Criteria::LIKE;
            }
        } elseif (\$comparison == Criteria::CONTAINS_NONE) {
            \$$variableName = '%| ' . \$$variableName . ' |%';
            \$comparison = Criteria::NOT_LIKE;
            \$key = \$this->getAliasedColName($qualifiedName);
            if (\$this->containsKey(\$key)) {
                \$this->addAnd(\$key, \$$variableName, \$comparison);
            } else {
                \$this->addAnd(\$key, \$$variableName, \$comparison);
            }
            \$this->addOr(\$key, null, Criteria::ISNULL);

            return \$this;
        }

        return \$this->addUsingAlias($qualifiedName, \$$variableName, \$comparison);
    }
";
    }

    /**
     * Adds the singular filterByCol method for an Array column.
     *
     * @param string &$script The script will be modified in this method.
     * @param Column $col
     */
    protected function addFilterBySetCol(&$script, Column $col)
    {
        $colPhpName = $col->getPhpName();
        $singularPhpName = $col->getPhpSingularName();
        $colName = $col->getName();
        $variableName = $col->getCamelCaseName();
        $script .= "
    /**
     * Filter the query on the $colName column
     * @param     mixed \$$variableName The value to use as filter
     * @param     string \$comparison Operator to use for the column comparison, defaults to Criteria::CONTAINS_ALL
     *
     * @return \$this|" . $this->getQueryClassName() . " The current query, for fluid interface
     */
    public function filterBy$singularPhpName(\$$variableName = null, \$comparison = null)
    {
        return \$this->filterBy$colPhpName(\$$variableName, \$comparison);
    }
";
    }

    /**
     * Adds the filterByFk method for this object.
     * @param string &$script The script will be modified in this method.
     * @param $fk ForeignKey
     */
    protected function addFilterByFk(&$script, $fk)
    {
        $this->declareClasses(
            '\Propel\Runtime\Collection\ObjectCollection',
            '\Propel\Runtime\Exception\PropelException'
        );
        $table = $this->getTable();
        $queryClass = $this->getQueryClassName();
        $fkTable = $fk->getForeignTable();
        $fkStubObjectBuilder = $this->getNewStubObjectBuilder($fkTable);
        $this->declareClassFromBuilder($fkStubObjectBuilder);
        $fkPhpName = $this->getClassNameFromBuilder($fkStubObjectBuilder, true);
        $relationName = $this->getFKPhpNameAffix($fk);
        $objectName = '$' . $fkTable->getCamelCaseName();
        $script .= "
    /**
     * Filter the query by a related $fkPhpName object
     *";
        if ($fk->isComposite()) {
            $script .= "
     * @param $fkPhpName $objectName The related object to use as filter";
        } else {
            $script .= "
     * @param $fkPhpName|ObjectCollection $objectName The related object(s) to use as filter";
        }
        $script .= "
     * @param string \$comparison Operator to use for the column comparison, defaults to Criteria::EQUAL
     *
     * @throws \\Propel\\Runtime\\Exception\\PropelException
     *
     * @return $queryClass The current query, for fluid interface
     */
    public function filterBy$relationName($objectName, \$comparison = null)
    {
        if ($objectName instanceof $fkPhpName) {
            return \$this";

        foreach ($fk->getMapping() as $mapping) {
            list($localColumn, $rightValueOrColumn) = $mapping;
            if ($rightValueOrColumn instanceof Column) {
                $script .= "
                ->addUsingAlias(" . $this->getColumnConstant($localColumn) . ", " . $objectName . "->get" . $rightValueOrColumn->getPhpName() . "(), \$comparison)";
            } else {
                $value = var_export($rightValueOrColumn, true);
                $script .= "
                ->addUsingAlias(" . $this->getColumnConstant($localColumn) . ", $value, \$comparison)";
            }
        }

        $script .= ";";
        if (!$fk->isComposite()) {
            $localColumnConstant = $this->getColumnConstant($fk->getLocalColumn());
            $foreignColumnName = $fk->getForeignColumn()->getPhpName();
            $keyColumn = $fk->getForeignTable()->hasCompositePrimaryKey() ? $foreignColumnName : 'PrimaryKey';
            $script .= "
        } elseif ($objectName instanceof ObjectCollection) {
            if (null === \$comparison) {
                \$comparison = Criteria::IN;
            }

            return \$this
                ->addUsingAlias($localColumnConstant, {$objectName}->toKeyValue('$keyColumn', '$foreignColumnName'), \$comparison);";
        }
        $script .= "
        } else {";
        if ($fk->isComposite()) {
            $script .= "
            throw new PropelException('filterBy$relationName() only accepts arguments of type $fkPhpName');";
        } else {
            $script .= "
            throw new PropelException('filterBy$relationName() only accepts arguments of type $fkPhpName or Collection');";
        }
        $script .= "
        }
    }
";
    }

    /**
     * Adds the filterByRefFk method for this object.
     *
     * @param string     &$script The script will be modified in this method.
     * @param ForeignKey $fk
     */
    protected function addFilterByRefFk(&$script, ForeignKey $fk)
    {
        $this->declareClasses(
            '\Propel\Runtime\Collection\ObjectCollection',
            '\Propel\Runtime\Exception\PropelException'
        );
        $queryClass = $this->getQueryClassName();
        $fkTable = $this->getTable()->getDatabase()->getTable($fk->getTableName());
        $fkStubObjectBuilder = $this->getNewStubObjectBuilder($fkTable);
        $this->declareClassFromBuilder($fkStubObjectBuilder);
        $fkPhpName = $this->getClassNameFromBuilder($fkStubObjectBuilder, true);
        $relationName = $this->getRefFKPhpNameAffix($fk);
        $objectName = '$' . $fkTable->getCamelCaseName();
        $script .= "
    /**
     * Filter the query by a related $fkPhpName object
     *
     * @param $fkPhpName|ObjectCollection $objectName the related object to use as filter
     * @param string \$comparison Operator to use for the column comparison, defaults to Criteria::EQUAL
     *
     * @return $queryClass The current query, for fluid interface
     */
    public function filterBy$relationName($objectName, \$comparison = null)
    {
        if ($objectName instanceof $fkPhpName) {
            return \$this";
        foreach ($fk->getInverseMapping() as $mapping) {
            /** @var Column $foreignColumn */
            list($localValueOrColumn, $foreignColumn) = $mapping;
            $rightValue = "{$objectName}->get" . $foreignColumn->getPhpName() . "()";

            if ($localValueOrColumn instanceof Column) {
                $script .= "
                ->addUsingAlias(" . $this->getColumnConstant($localValueOrColumn) . ", $rightValue, \$comparison)";
            } else {
                $leftValue = var_export($localValueOrColumn, true);
                $bindingType = $foreignColumn->getPDOType();
                $script .= "
                ->where(\"$leftValue = ?\", $rightValue, $bindingType)";
            }

        }
        $script .= ";";
        if (!$fk->isComposite()) {
            $script .= "
        } elseif ($objectName instanceof ObjectCollection) {
            return \$this
                ->use{$relationName}Query()
                ->filterByPrimaryKeys({$objectName}->getPrimaryKeys())
                ->endUse();";
        }
        $script .= "
        } else {";
        if ($fk->isComposite()) {
            $script .= "
            throw new PropelException('filterBy$relationName() only accepts arguments of type $fkPhpName');";
        } else {
            $script .= "
            throw new PropelException('filterBy$relationName() only accepts arguments of type $fkPhpName or Collection');";
        }
        $script .= "
        }
    }
";
    }

    /**
     * Adds the joinFk method for this object.
     * @param string &$script The script will be modified in this method.
     * @param $fk ForeignKey
     */
    protected function addJoinFk(&$script, $fk)
    {
        $queryClass = $this->getQueryClassName();
        $fkTable = $fk->getForeignTable();
        $relationName = $this->getFKPhpNameAffix($fk);
        $joinType = $this->getJoinType($fk);
        $this->addJoinRelated($script, $fkTable, $queryClass, $relationName, $joinType);
    }

    /**
     * Adds the joinRefFk method for this object.
     * @param string     &$script The script will be modified in this method.
     * @param ForeignKey $fk
     */
    protected function addJoinRefFk(&$script, ForeignKey $fk)
    {
        $queryClass = $this->getQueryClassName();
        $fkTable = $this->getTable()->getDatabase()->getTable($fk->getTableName());
        $relationName = $this->getRefFKPhpNameAffix($fk);
        $joinType = $this->getJoinType($fk);
        $this->addJoinRelated($script, $fkTable, $queryClass, $relationName, $joinType);
    }

    /**
     * Adds a joinRelated method for this object.
     * @param string &$script The script will be modified in this method.
     */
    protected function addJoinRelated(&$script, $fkTable, $queryClass, $relationName, $joinType)
    {
        $script .= "
    /**
     * Adds a JOIN clause to the query using the " . $relationName . " relation
     *
     * @param     string \$relationAlias optional alias for the relation
     * @param     string \$joinType Accepted values are null, 'left join', 'right join', 'inner join'
     *
     * @return \$this|". $queryClass . " The current query, for fluid interface
     */
    public function join" . $relationName . "(\$relationAlias = null, \$joinType = " . $joinType . ")
    {
        \$tableMap = \$this->getTableMap();
        \$relationMap = \$tableMap->getRelation('" . $relationName . "');

        // create a ModelJoin object for this join
        \$join = new ModelJoin();
        \$join->setJoinType(\$joinType);
        \$join->setRelationMap(\$relationMap, \$this->useAliasInSQL ? \$this->getModelAlias() : null, \$relationAlias);
        if (\$previousJoin = \$this->getPreviousJoin()) {
            \$join->setPreviousJoin(\$previousJoin);
        }

        // add the ModelJoin to the current object
        if (\$relationAlias) {
            \$this->addAlias(\$relationAlias, \$relationMap->getRightTable()->getName());
            \$this->addJoinObject(\$join, \$relationAlias);
        } else {
            \$this->addJoinObject(\$join, '" . $relationName . "');
        }

        return \$this;
    }
";
    }

    /**
     * Adds the useFkQuery method for this object.
     * @param string &$script The script will be modified in this method.
     * @param $fk ForeignKey
     */
    protected function addUseFkQuery(&$script, $fk)
    {
        $fkTable = $fk->getForeignTable();
        $fkQueryBuilder = $this->getNewStubQueryBuilder($fkTable);
        $queryClass = $this->getClassNameFromBuilder($fkQueryBuilder, true);
        $relationName = $this->getFKPhpNameAffix($fk);
        $joinType = $this->getJoinType($fk);

        $this->addUseRelatedQuery($script, $fkTable, $queryClass, $relationName, $joinType);
    }

    /**
     * Adds the useFkQuery method for this object.
     * @param string     &$script The script will be modified in this method.
     * @param ForeignKey $fk
     */
    protected function addUseRefFkQuery(&$script, ForeignKey $fk)
    {
        $fkTable = $this->getTable()->getDatabase()->getTable($fk->getTableName());
        $fkQueryBuilder = $this->getNewStubQueryBuilder($fkTable);
        $queryClass = $this->getClassNameFromBuilder($fkQueryBuilder, true);
        $relationName = $this->getRefFKPhpNameAffix($fk);
        $joinType = $this->getJoinType($fk);

        $this->addUseRelatedQuery($script, $fkTable, $queryClass, $relationName, $joinType);
    }

    /**
     * Adds a useRelatedQuery method for this object.
     * @param string &$script The script will be modified in this method.
     */
    protected function addUseRelatedQuery(&$script, Table $fkTable, $queryClass, $relationName, $joinType)
    {
        $script .= "
    /**
     * Use the $relationName relation " . $fkTable->getPhpName() . " object
     *
     * @see useQuery()
     *
     * @param     string \$relationAlias optional alias for the relation,
     *                                   to be used as main alias in the secondary query
     * @param     string \$joinType Accepted values are null, 'left join', 'right join', 'inner join'
     *
     * @return $queryClass A secondary query class using the current class as primary query
     */
    public function use" . $relationName . "Query(\$relationAlias = null, \$joinType = " . $joinType . ")
    {
        return \$this
            ->join" . $relationName . "(\$relationAlias, \$joinType)
            ->useQuery(\$relationAlias ? \$relationAlias : '$relationName', '$queryClass');
    }
";
    }

    protected function addFilterByCrossFK(&$script, CrossForeignKeys $crossFKs)
    {
        $relationName = $this->getRefFKPhpNameAffix($crossFKs->getIncomingForeignKey(), $plural = false);

        foreach ($crossFKs->getCrossForeignKeys() as $crossFK) {
            $queryClass = $this->getQueryClassName();
            $crossRefTable = $crossFK->getTable();
            $foreignTable = $crossFK->getForeignTable();
            $fkPhpName =  $foreignTable->getPhpName();
            $crossTableName = $crossRefTable->getName();
            $relName = $this->getFKPhpNameAffix($crossFK, $plural = false);
            $objectName = '$' . $foreignTable->getCamelCaseName();
            $script .= "
    /**
     * Filter the query by a related $fkPhpName object
     * using the $crossTableName table as cross reference
     *
     * @param $fkPhpName $objectName the related object to use as filter
     * @param string \$comparison Operator to use for the column comparison, defaults to Criteria::EQUAL
     *
     * @return $queryClass The current query, for fluid interface
     */
    public function filterBy{$relName}($objectName, \$comparison = Criteria::EQUAL)
    {
        return \$this
            ->use{$relationName}Query()
            ->filterBy{$relName}($objectName, \$comparison)
            ->endUse();
    }
";
        }
    }

    /**
     * Adds the prune method for this object.
     * @param string &$script The script will be modified in this method.
     */
    protected function addPrune(&$script)
    {
        $table = $this->getTable();
        $class = $this->getObjectClassName();
        $objectName = '$' . $table->getCamelCaseName();

        $script .= "
    /**
     * Exclude object from result
     *
     * @param   $class $objectName Object to remove from the list of results
     *
     * @return \$this|" . $this->getQueryClassName() . " The current query, for fluid interface
     */
    public function prune($objectName = null)
    {
        if ($objectName) {";
        $pks = $table->getPrimaryKey();
        if (count($pks) > 1) {
            $i = 0;
            $conditions = [];
            foreach ($pks as $col) {
                $const = $this->getColumnConstant($col);
                $condName = "'pruneCond" . $i . "'";
                $conditions[]= $condName;
                $script .= "
            \$this->addCond(". $condName . ", \$this->getAliasedColName($const), " . $objectName . "->get" . $col->getPhpName() . "(), Criteria::NOT_EQUAL);";
                $i++;
            }
            $conditionsString = implode(', ', $conditions);
            $script .= "
            \$this->combine(array(" . $conditionsString . "), Criteria::LOGICAL_OR);";
        } elseif ($table->hasPrimaryKey()) {
            $col = $pks[0];
            $const = $this->getColumnConstant($col);
            $script .= "
            \$this->addUsingAlias($const, " . $objectName . "->get" . $col->getPhpName() . "(), Criteria::NOT_EQUAL);";
        } else {
            $this->declareClass('Propel\\Runtime\\Exception\\LogicException');
            $script .= "
            throw new LogicException('{$this->getObjectName()} object has no primary key');
";
        }
        $script .= "
        }

        return \$this;
    }
";
    }

    /**
     * Adds the basePreSelect hook for this object.
     * @param string &$script The script will be modified in this method.
     */
    protected function addBasePreSelect(&$script)
    {
        $behaviorCode = '';
        $this->applyBehaviorModifier('preSelectQuery', $behaviorCode, "        ");
        if (!$behaviorCode) {
            return;
        }
        $script .= "
    /**
     * Code to execute before every SELECT statement
     *
     * @param     ConnectionInterface \$con The connection object used by the query
     */
    protected function basePreSelect(ConnectionInterface \$con)
    {" . $behaviorCode . "

        return \$this->preSelect(\$con);
    }
";
    }

    /**
     * Adds the basePreDelete hook for this object.
     * @param string &$script The script will be modified in this method.
     */
    protected function addBasePreDelete(&$script)
    {
        $behaviorCode = '';
        $this->applyBehaviorModifier('preDeleteQuery', $behaviorCode, "        ");
        if (!$behaviorCode) {
            return;
        }
        $script .= "
    /**
     * Code to execute before every DELETE statement
     *
     * @param     ConnectionInterface \$con The connection object used by the query
     */
    protected function basePreDelete(ConnectionInterface \$con)
    {" . $behaviorCode . "

        return \$this->preDelete(\$con);
    }
";
    }

    /**
     * Adds the basePostDelete hook for this object.
     * @param string &$script The script will be modified in this method.
     */
    protected function addBasePostDelete(&$script)
    {
        $behaviorCode = '';
        $this->applyBehaviorModifier('postDeleteQuery', $behaviorCode, "        ");
        if (!$behaviorCode) {
            return;
        }
        $script .= "
    /**
     * Code to execute after every DELETE statement
     *
     * @param     int \$affectedRows the number of deleted rows
     * @param     ConnectionInterface \$con The connection object used by the query
     */
    protected function basePostDelete(\$affectedRows, ConnectionInterface \$con)
    {" . $behaviorCode . "

        return \$this->postDelete(\$affectedRows, \$con);
    }
";
    }

    /**
     * Adds the basePreUpdate hook for this object.
     * @param string &$script The script will be modified in this method.
     */
    protected function addBasePreUpdate(&$script)
    {
        $behaviorCode = '';
        $this->applyBehaviorModifier('preUpdateQuery', $behaviorCode, "        ");
        if (!$behaviorCode) {
            return;
        }
        $script .= "
    /**
     * Code to execute before every UPDATE statement
     *
     * @param     array \$values The associative array of columns and values for the update
     * @param     ConnectionInterface \$con The connection object used by the query
     * @param     boolean \$forceIndividualSaves If false (default), the resulting call is a Criteria::doUpdate(), otherwise it is a series of save() calls on all the found objects
     */
    protected function basePreUpdate(&\$values, ConnectionInterface \$con, \$forceIndividualSaves = false)
    {" . $behaviorCode . "

        return \$this->preUpdate(\$values, \$con, \$forceIndividualSaves);
    }
";
    }

    /**
     * Adds the basePostUpdate hook for this object.
     * @param string &$script The script will be modified in this method.
     */
    protected function addBasePostUpdate(&$script)
    {
        $behaviorCode = '';
        $this->applyBehaviorModifier('postUpdateQuery', $behaviorCode, "        ");
        if (!$behaviorCode) {
            return;
        }
        $script .= "
    /**
     * Code to execute after every UPDATE statement
     *
     * @param     int \$affectedRows the number of updated rows
     * @param     ConnectionInterface \$con The connection object used by the query
     */
    protected function basePostUpdate(\$affectedRows, ConnectionInterface \$con)
    {" . $behaviorCode . "

        return \$this->postUpdate(\$affectedRows, \$con);
    }
";
    }

    /**
     * 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"
     * @return boolean
     */
    public function hasBehaviorModifier($hookName, $modifier = null)
    {
        return parent::hasBehaviorModifier($hookName, 'QueryBuilderModifier');
    }

    /**
     * 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.
     */
    public function applyBehaviorModifier($hookName, &$script, $tab = "        ")
    {
        return $this->applyBehaviorModifierBase($hookName, 'QueryBuilderModifier', $script, $tab);
    }

    /**
     * Checks whether any registered behavior content creator on that table exists a contentName
     * @param string $contentName The name of the content as called from one of this class methods, e.g. "parentClassName"
     */
    public function getBehaviorContent($contentName)
    {
        return $this->getBehaviorContentBase($contentName, 'QueryBuilderModifier');
    }

    /**
     * Adds the doDelete() method.
     * @param string &$script The script will be modified in this method.
     */
    protected function addDelete(&$script)
    {
        $script .= "
    /**
     * Performs a DELETE on the database based on the current ModelCriteria
     *
     * @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 function delete(ConnectionInterface \$con = null)
    {
        if (null === \$con) {
            \$con = Propel::getServiceContainer()->getWriteConnection(" . $this->getTableMapClass() . "::DATABASE_NAME);
        }

        \$criteria = \$this;

        // Set the correct dbName
        \$criteria->setDbName(" . $this->getTableMapClass() . "::DATABASE_NAME);

        // use transaction because \$criteria could contain info
        // for more than one table or we could emulating ON DELETE CASCADE, etc.
        return \$con->transaction(function () use (\$con, \$criteria) {
            \$affectedRows = 0; // initialize var to track total num of affected rows
            ";

        if ($this->isDeleteCascadeEmulationNeeded()) {
            $script .= "
            // cloning the Criteria in case it's modified by doSelect() or doSelectStmt()
            \$c = clone \$criteria;
            \$affectedRows += \$c->doOnDeleteCascade(\$con);
            ";
        }

        if ($this->isDeleteSetNullEmulationNeeded()) {
            $script .= "
            // cloning the Criteria in case it's modified by doSelect() or doSelectStmt()
            \$c = clone \$criteria;
            \$c->doOnDeleteSetNull(\$con);
            ";
        }

        $script .= "
            {$this->getTableMapClassName()}::removeInstanceFromPool(\$criteria);
        ";

        $script .= "
            \$affectedRows += ModelCriteria::delete(\$con);
            {$this->getTableMapClassName()}::clearRelatedInstancePool();

            return \$affectedRows;
        });
    }
";
    }

    /**
     * Adds the doOnDeleteCascade() method, which provides ON DELETE CASCADE emulation.
     * @param string &$script The script will be modified in this method.
     */
    protected function addDoOnDeleteCascade(&$script)
    {
        $table = $this->getTable();
        $script .= "
    /**
     * This is a method for emulating ON DELETE CASCADE for DBs that don't support this
     * feature (like MySQL or SQLite).
     *
     * This method is not very speedy because it must perform a query first to get
     * the implicated records and then perform the deletes by calling those Query classes.
     *
     * This method should be used within a transaction if possible.
     *
     * @param ConnectionInterface \$con
     * @return int The number of affected rows (if supported by underlying database driver).
     */
    protected function doOnDeleteCascade(ConnectionInterface \$con)
    {
        // initialize var to track total num of affected rows
        \$affectedRows = 0;

        // first find the objects that are implicated by the \$this
        \$objects = {$this->getQueryClassName()}::create(null, \$this)->find(\$con);
        foreach (\$objects as \$obj) {
";

        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);

            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.)

                $fkClassName = $joinedTableTableMapBuilder->getObjectClassName();

                if (ForeignKey::CASCADE === $fk->getOnDelete()) {

                    // backwards on purpose
                    $columnNamesF = $fk->getLocalColumns();
                    $columnNamesL = $fk->getForeignColumns();

                    $this->declareClassFromBuilder($joinedTableTableMapBuilder->getTableMapBuilder());

                    $script .= "

            // delete related $fkClassName objects
            \$query = new ".$joinedTableTableMapBuilder->getQueryClassName(true).";
            ";
                    for ($x = 0, $xlen = count($columnNamesF); $x < $xlen; $x++) {
                        $columnFK = $tblFK->getColumn($columnNamesF[$x]);
                        $columnL = $table->getColumn($columnNamesL[$x]);

                        $script .= "
            \$query->add(".$joinedTableTableMapBuilder->getColumnConstant($columnFK) .", \$obj->get".$columnL->getPhpName()."());";
                    }

                    $script .= "
            \$affectedRows += \$query->delete(\$con);";

                } // if cascade && fkey table name != curr table name

            } // if not for ref only
        } // foreach foreign keys
        $script .= "
        }

        return \$affectedRows;
    }
";
    } // end addDoOnDeleteCascade


    /**
     * Adds the doOnDeleteSetNull() method, which provides ON DELETE SET NULL emulation.
     * @param string &$script The script will be modified in this method.
     */
    protected function addDoOnDeleteSetNull(&$script)
    {
        $table = $this->getTable();
        $script .= "
    /**
     * This is a method for emulating ON DELETE SET NULL DBs that don't support this
     * feature (like MySQL or SQLite).
     *
     * This method is not very speedy because it must perform a query first to get
     * the implicated records and then perform the deletes by calling those query classes.
     *
     * This method should be used within a transaction if possible.
     *
     * @param ConnectionInterface \$con
     * @return void
     */
    protected function doOnDeleteSetNull(ConnectionInterface \$con)
    {
        // first find the objects that are implicated by the \$this
        \$objects = {$this->getQueryClassName()}::create(null, \$this)->find(\$con);
        foreach (\$objects as \$obj) {
";

        // This logic is almost exactly the same as that in doOnDeleteCascade()
        // it may make sense to refactor this, provided that things don't
        // get too complicated.
        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();
            $refTableTableMapBuilder = $this->getNewTableMapBuilder($tblFK);

            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.)

                $fkClassName = $refTableTableMapBuilder->getObjectClassName();

                if (ForeignKey::SETNULL === $fk->getOnDelete()) {
                    // backwards on purpose
                    $columnNamesF = $fk->getLocalColumns();
                    $columnNamesL = $fk->getForeignColumns(); // should be same num as foreign

                    $this->declareClassFromBuilder($refTableTableMapBuilder);

                    $script .= "
            // set fkey col in related $fkClassName rows to NULL
            \$query = new " . $refTableTableMapBuilder->getQueryClassName(true) . "();
            \$updateValues = new Criteria();";

                    for ($x = 0, $xlen = count($columnNamesF); $x < $xlen; $x++) {
                        $columnFK = $tblFK->getColumn($columnNamesF[$x]);
                        $columnL = $table->getColumn($columnNamesL[$x]);
                        $script .= "
            \$query->add(".$refTableTableMapBuilder->getColumnConstant($columnFK).", \$obj->get".$columnL->getPhpName()."());
            \$updateValues->add(".$refTableTableMapBuilder->getColumnConstant($columnFK).", null);
";
                    }

                    $script .= "\$query->update(\$updateValues, \$con);
";
                } // if setnull && fkey table name != curr table name
            } // if not for ref only
        } // foreach foreign keys

        $script .= "
        }
    }
";
    }


    /**
     * 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 function doDeleteAll(ConnectionInterface \$con = null)
    {
        if (null === \$con) {
            \$con = Propel::getServiceContainer()->getWriteConnection(" . $this->getTableMapClass() . "::DATABASE_NAME);
        }

        // use transaction because \$criteria could contain info
        // for more than one table or we could emulating ON DELETE CASCADE, etc.
        return \$con->transaction(function () use (\$con) {
            \$affectedRows = 0; // initialize var to track total num of affected rows
            ";
        if ($this->isDeleteCascadeEmulationNeeded()) {
            $script .="\$affectedRows += \$this->doOnDeleteCascade(\$con);
            ";
        }
        if ($this->isDeleteSetNullEmulationNeeded()) {
            $script .= "\$this->doOnDeleteSetNull(\$con);
            ";
        }
        $script .= "\$affectedRows += parent::doDeleteAll(\$con);
            // Because this db requires some delete cascade/set null emulation, we have to
            // clear the cached instance *after* the emulation has happened (since
            // instances get re-added by the select statement contained therein).
            {$this->getTableMapClassName()}::clearInstancePool();
            {$this->getTableMapClassName()}::clearRelatedInstancePool();

            return \$affectedRows;
        });
    }
";
    }

}

Size

Lines of code
1128