Inital commit
This commit is contained in:
39
core/vendor/propel/propel/.gitignore
vendored
Normal file
39
core/vendor/propel/propel/.gitignore
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
vendor/
|
||||
composer.phar
|
||||
composer.lock
|
||||
autoload.php
|
||||
phpunit.xml
|
||||
pom.xml
|
||||
php-cs-fixer.phar
|
||||
|
||||
generated-classes/
|
||||
|
||||
tests/Fixtures/namespaced/build/
|
||||
tests/Fixtures/nestedset/build/
|
||||
tests/Fixtures/schemas/build/
|
||||
tests/Fixtures/schemas/build/
|
||||
|
||||
tests/Fixtures/bookstore/build/
|
||||
tests/Fixtures/bookstore/runtime-conf.xml
|
||||
tests/Fixtures/bookstore/build.properties
|
||||
|
||||
tests/Fixtures/bookstore-packaged/build/
|
||||
tests/Fixtures/bookstore-packaged/build.properties
|
||||
tests/Fixtures/bookstore-packaged/runtime-conf.xml
|
||||
|
||||
tests/Fixtures/namespaced/runtime-conf.xml
|
||||
tests/Fixtures/namespaced/build.properties
|
||||
|
||||
tests/Fixtures/schemas/runtime-conf.xml
|
||||
tests/Fixtures/schemas/build.properties
|
||||
|
||||
tests/Fixtures/reverse/mysql/build/
|
||||
tests/Fixtures/reverse/mysql/build.properties
|
||||
tests/Fixtures/reverse/mysql/runtime-conf.xml
|
||||
|
||||
tests/Fixtures/reverse/pgsql/build/
|
||||
tests/Fixtures/reverse/pgsql/runtime-conf.xml
|
||||
|
||||
tests/Fixtures/migration/build/
|
||||
tests/Fixtures/migration/build.properties
|
||||
tests/Fixtures/migration/runtime-conf.xml
|
||||
25
core/vendor/propel/propel/.travis.yml
vendored
Normal file
25
core/vendor/propel/propel/.travis.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
language: php
|
||||
|
||||
php:
|
||||
- 5.4
|
||||
- 5.5
|
||||
- hhvm
|
||||
|
||||
env:
|
||||
- DB=mysql DB_USER=root
|
||||
- DB=pgsql
|
||||
- DB=sqlite
|
||||
|
||||
before_script:
|
||||
# Composer
|
||||
- wget http://getcomposer.org/composer.phar
|
||||
- php composer.phar install --prefer-source
|
||||
|
||||
- ./tests/bin/setup.$DB.sh;
|
||||
|
||||
script:
|
||||
- ./tests/bin/phpunit.$DB.sh;
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- php: hhvm
|
||||
20
core/vendor/propel/propel/LICENSE
vendored
Normal file
20
core/vendor/propel/propel/LICENSE
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
Copyright (c) 2005-2011 Hans Lellelid, David Zuelke, Francois Zaninotto, William
|
||||
Durand
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
38
core/vendor/propel/propel/README.md
vendored
Normal file
38
core/vendor/propel/propel/README.md
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
# Propel2 #
|
||||
|
||||
Propel2 is an open-source Object-Relational Mapping (ORM) for PHP 5.4.
|
||||
|
||||
[](http://travis-ci.org/propelorm/Propel2)
|
||||
|
||||
|
||||
## Requirements ##
|
||||
|
||||
Propel2 uses the following Symfony2 Components:
|
||||
|
||||
* [Console](https://github.com/symfony/Console)
|
||||
* [Yaml](https://github.com/symfony/Yaml)
|
||||
* [Finder](https://github.com/symfony/Finder)
|
||||
* [Validator](https://github.com/symfony/Validator)
|
||||
* [Filesystem](https://github.com/symfony/Filesystem)
|
||||
|
||||
Propel2 also relies on [**Composer**](https://github.com/composer/composer) to manage dependencies but you
|
||||
also can use [ClassLoader](https://github.com/symfony/ClassLoader) (see the `autoload.php.dist` file for instance).
|
||||
|
||||
Propel2 is only supported on PHP 5.4 and up.
|
||||
|
||||
|
||||
## Installation ##
|
||||
|
||||
Read the [Propel documentation](http://www.propelorm.org/).
|
||||
|
||||
|
||||
## Contribute ##
|
||||
|
||||
Everybody can contribute to Propel2. Just fork it, and send Pull Requests.
|
||||
You have to follow [Propel2 Coding Standards](https://github.com/propelorm/Propel2/wiki/Coding-Standards) and provides unit tests as much as possible.
|
||||
|
||||
Please see our [contribution guideline](https://github.com/propelorm/propelorm.github.com/blob/master/contribute.markdown). Thank you!
|
||||
|
||||
## License ##
|
||||
|
||||
See the `LICENSE` file.
|
||||
157
core/vendor/propel/propel/UPDATE.md
vendored
Normal file
157
core/vendor/propel/propel/UPDATE.md
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
# List of Backwards Incompatible Changes
|
||||
|
||||
## Tasks become Commands... and change names
|
||||
|
||||
The Phing tasks that you used at buildtime are now refactored to Commands using the Symfony2 Command component. They work the same, but their name has changed.
|
||||
|
||||
Replace... With...
|
||||
build-model model:build
|
||||
build-sql sql:build
|
||||
insert-sql sql:insert
|
||||
convert-conf config:convert-xml
|
||||
diff [not yet refactored]
|
||||
status migration:status
|
||||
migrate [not yet refactored]
|
||||
up migration:up
|
||||
down migration:down
|
||||
reverse [not yet refactored]
|
||||
|
||||
## `Propel\Runtime\Propel` methods renamed.
|
||||
|
||||
Some static methods from the `Propel` class have been renamed. Therefore, you must replace the following occurrences in your code:
|
||||
|
||||
Replace... With...
|
||||
Propel::CONNECTION_WRITE ServiceContainerInterface::CONNECTION_WRITE
|
||||
Propel::CONNECTION_READ ServiceContainerInterface::CONNECTION_READ
|
||||
Propel::getDB($name) Propel::getAdapter($name)
|
||||
Propel::getConnection($name, Propel::CONNECTION_READ) Propel::getReadConnection($name)
|
||||
Propel::getConnection($name, Propel::CONNECTION_WRITE) Propel::getWriteConnection($name)
|
||||
Propel::getDefaultDB() Propel::getDefaultDatasource()
|
||||
|
||||
The generated model is automatically updated once you rebuild your model.
|
||||
|
||||
>**Tip**: Internally, `Propel::getAdapter()` proxies to `Propel::getServiceContainer()->getAdapter()`. The `Propel` class was refactored to keep only one static class and to be more extensible. It remains the easy entry point to all the necessary services provided by Propel.
|
||||
|
||||
`Propel::setConnection()` is removed. As for `Propel::init($configFilePath)`, where `$configFilePath` is the path to the PHP configuration generated by the `config:convert-xml` command, you can now replace it with `include $configFilePath`.
|
||||
## Builders renamed
|
||||
|
||||
The classes used by Propel internally to build the object model were renamed. This affects your project if you extended one of these classes.
|
||||
|
||||
Replace... With...
|
||||
OMBuilder.php AbstractOMBuilder.php
|
||||
ObjectBuilder.php AbstractObjectBuilder.php
|
||||
PeerBuilder.php __removed__
|
||||
PHP5ExtensionObjectBuilder.php ExtensionObjectBuilder.php
|
||||
PHP5ExtensionPeerBuilder.php __removed__
|
||||
PHP5InterfaceBuilder.php InterfaceBuilder.php
|
||||
PHP5MultiExtendObjectBuilder.php MultiExtendObjectBuilder.php
|
||||
PHP5ObjectBuilder.php ObjectBuilder.php
|
||||
PHP5PeerBuilder.php __removed__
|
||||
PHP5TableMapBuilder.php TableMapBuilder.php
|
||||
|
||||
## Base classes reorganized
|
||||
|
||||
Base classes are generated in a `Base` directory, and base classes are no more prefixed by `Base`.
|
||||
|
||||
Parameters `basePrefix` and `namespaceOm` have been removed
|
||||
|
||||
## `Propel\Generator\Model\Database` methods renamed.
|
||||
|
||||
Before:
|
||||
|
||||
public function setAppData(AppData $parent)
|
||||
|
||||
After:
|
||||
|
||||
public function setParentSchema(Schema $parent)
|
||||
|
||||
Before:
|
||||
|
||||
public function getAppData()
|
||||
|
||||
After:
|
||||
|
||||
public function getParentSchema()
|
||||
|
||||
## `Propel\Generator\Model\AppData` class has been renamed to `Schema`.
|
||||
|
||||
The `AppData::joinAppDatas` method has been renamed to `Schema::joinSchemas`.
|
||||
|
||||
Before:
|
||||
|
||||
public function joinAppDatas($ads)
|
||||
|
||||
After:
|
||||
|
||||
public function joinSchemas($schemas)
|
||||
|
||||
## `Propel\Generator\Builder\Util\XmlToAppData` class has been renamed to `SchemaReader`.
|
||||
|
||||
Both `SchemaReader::parseString` and `SchemaReader::parseFile` methods return
|
||||
a `Propel\Generator\Model\Schema` object instead of a `Propel\Generator\Model\AppData` object.
|
||||
|
||||
## `Propel\Generator\Util\SchemaValidator` constructor signature changed.
|
||||
|
||||
Before:
|
||||
|
||||
public function __construct(AppData $appData)
|
||||
|
||||
After:
|
||||
|
||||
public function __construct(Schema $schema)
|
||||
|
||||
## `Propel\Generator\Model\Table::containsColumn` method has been removed.
|
||||
|
||||
## `Propel\Generator\Model\VendorInfo::addParameter` method has been removed.
|
||||
|
||||
## `Propel\Generator\Model\Column::setTypeFromString` method has been removed.
|
||||
|
||||
## `Propel\Generator\Model\Column::getPropelType` method has been removed.
|
||||
|
||||
## `Propel\Generator\Model\Column::getDefaultSetting` method has been removed.
|
||||
|
||||
## `Propel\Generator\Model\Column::makeList` method has been removed.
|
||||
|
||||
## `Propel\Generator\Model\Column::printSize` method has been renamed to `Propel\Generator\Model\Column::getSizeDefinition`.
|
||||
|
||||
## `Propel\Generator\Model\ForeignKey::getLocalColumnNames` method has been removed.
|
||||
|
||||
## `Propel\Generator\Model\ForeignKey::getForeignColumnNames` method has been removed.
|
||||
|
||||
## `Propel\Generator\Model\Domain::printSize` method has been renamed to
|
||||
`Propel\Generator\Model\Domain::getSizeDefinition`.
|
||||
|
||||
## `Propel\Generator\Model\Table::printPrimaryKey` method has been removed.
|
||||
|
||||
## `Propel\Generator\Model\Table::printList` method has been removed.
|
||||
|
||||
## `Propel\Generator\Model\PropelTypes::getCreoleTypes` method has been removed.
|
||||
|
||||
## `Propel\Generator\Model\ScopedElement` class has been renamed to `Propel\Generator\Model\ScopedMappingModel`.
|
||||
|
||||
## `Propel\Generator\Model\XmlElement` class has been renamed to `Propel\Generator\Model\MappingModel`.
|
||||
|
||||
## `Propel\Generator\Model\XmlElement::loadFromXml` method has been renamed to `Propel\Generator\Model\MappingModel::loadMapping`.
|
||||
|
||||
## `Propel\Runtime\Om\BaseObject` class has been removed.
|
||||
|
||||
## `Propel\Runtime\ActiveQuery\Criteria::addOr` operates only on existing conditions, where prior it would `OR` to a condition to
|
||||
on the same column (if it existed).
|
||||
|
||||
E.g.
|
||||
```php
|
||||
$criteria->add('column1', 'value');
|
||||
$criteria->add('column2', 'value');
|
||||
$criteria->addOr('column1', 'value'); // this used to be OR`ed to the first add (matched by name)
|
||||
```
|
||||
|
||||
All base object methods have been merged in generated Base Object classes.
|
||||
This could break, behaviors that call `parent` methods
|
||||
|
||||
## `Propel\Runtime\Om\Persistent` Interface replaced by `Propel\Runtime\Om\ActiveRecordInterface`
|
||||
|
||||
All methods from `Propel\Runtime\Om\Persistent` Interface have been removed
|
||||
All Base Object classes now implements `Propel\Runtime\Om\ActiveRecordInterface` this could be use to identify a Propel Object
|
||||
|
||||
## `Propel\Runtime\Util\PropelModelPager::count()` now return the number of items in the collection.
|
||||
To get the old behavior use `Propel\Runtime\Util\PropelModelPager::getNbResults()`.
|
||||
33
core/vendor/propel/propel/autoload.php.dist
vendored
Normal file
33
core/vendor/propel/propel/autoload.php.dist
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
if (file_exists($file = __DIR__.'/vendor/autoload.php')) {
|
||||
$loader = require $file;
|
||||
|
||||
$loader->add('Foo', __DIR__ . '/tests/Fixtures/namespaced/build/classes');
|
||||
$loader->add('Baz', __DIR__ . '/tests/Fixtures/namespaced/build/classes');
|
||||
$loader->add('Propel\Tests', array(
|
||||
__DIR__ . '/tests',
|
||||
__DIR__ . '/tests/Fixtures/bookstore/build/classes',
|
||||
__DIR__ . '/tests/Fixtures/schemas/build/classes'
|
||||
));
|
||||
$loader->register();
|
||||
} elseif (file_exists($file = __DIR__ . '/vendor/Symfony/Component/ClassLoader/UniversalClassLoader.php')) {
|
||||
require_once $file;
|
||||
|
||||
$loader = new \Symfony\Component\ClassLoader\UniversalClassLoader();
|
||||
$loader->registerNamespaces(array(
|
||||
'Propel\Common' => __DIR__ . '/src',
|
||||
'Propel\Runtime' => __DIR__ . '/src',
|
||||
'Propel\Generator' => __DIR__ . '/src',
|
||||
'Symfony\Component' => __DIR__ . '/vendor',
|
||||
'Monolog' => __DIR__ . '/vendor/Monolog/src/',
|
||||
'Foo' => __DIR__ . '/tests/Fixtures/namespaced/build/classes',
|
||||
'Baz' => __DIR__ . '/tests/Fixtures/namespaced/build/classes',
|
||||
'Propel\Tests' => array(
|
||||
__DIR__ . '/tests',
|
||||
__DIR__ . '/tests/Fixtures/bookstore/build/classes',
|
||||
__DIR__ . '/tests/Fixtures/schemas/build/classes',
|
||||
),
|
||||
));
|
||||
$loader->register();
|
||||
}
|
||||
4
core/vendor/propel/propel/bin/propel
vendored
Executable file
4
core/vendor/propel/propel/bin/propel
vendored
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
include('propel.php');
|
||||
9
core/vendor/propel/propel/bin/propel.bat
vendored
Executable file
9
core/vendor/propel/propel/bin/propel.bat
vendored
Executable file
@@ -0,0 +1,9 @@
|
||||
@echo off
|
||||
|
||||
if "%PHPBIN%" == "" set PHPBIN=php
|
||||
if not exist "%PHPBIN%" if "%PHP_PEAR_PHP_BIN%" neq "" goto USE_PEAR_PATH
|
||||
GOTO RUN
|
||||
:USE_PEAR_PATH
|
||||
set PHPBIN=%PHP_PEAR_PHP_BIN%
|
||||
:RUN
|
||||
"%PHPBIN%" "bin\propel" %*
|
||||
29
core/vendor/propel/propel/bin/propel.php
vendored
Normal file
29
core/vendor/propel/propel/bin/propel.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
if (!class_exists('\Symfony\Component\Console\Application')) {
|
||||
if (file_exists($file = __DIR__.'/../../../autoload.php') || file_exists($file = __DIR__.'/../autoload.php')) {
|
||||
require_once $file;
|
||||
} elseif (file_exists($file = __DIR__.'/../autoload.php.dist')) {
|
||||
require_once $file;
|
||||
}
|
||||
}
|
||||
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
use Propel\Runtime\Propel;
|
||||
|
||||
$finder = new Finder();
|
||||
$finder->files()->name('*.php')->in(__DIR__.'/../src/Propel/Generator/Command');
|
||||
|
||||
$app = new Application('Propel', Propel::VERSION);
|
||||
|
||||
foreach ($finder as $file) {
|
||||
$ns = '\\Propel\\Generator\\Command';
|
||||
$r = new \ReflectionClass($ns.'\\'.$file->getBasename('.php'));
|
||||
if ($r->isSubclassOf('Symfony\\Component\\Console\\Command\\Command') && !$r->isAbstract()) {
|
||||
$app->add($r->newInstance());
|
||||
}
|
||||
}
|
||||
|
||||
$app->run();
|
||||
48
core/vendor/propel/propel/composer.json
vendored
Normal file
48
core/vendor/propel/propel/composer.json
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "propel/propel",
|
||||
"type": "library",
|
||||
"description": "Propel2 is an open-source Object-Relational Mapping (ORM) for PHP 5.4",
|
||||
"keywords": [
|
||||
"ORM",
|
||||
"persistence",
|
||||
"Active Record"
|
||||
],
|
||||
"homepage": "http://www.propelorm.org/",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "William Durand",
|
||||
"email": "william.durand1@gmail.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.4",
|
||||
"symfony/yaml": "~2.2",
|
||||
"symfony/console": "~2.2",
|
||||
"symfony/finder": "~2.2",
|
||||
"symfony/validator": "~2.2",
|
||||
"symfony/filesystem": "~2.2",
|
||||
"psr/log": "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"behat/behat": "~2.4",
|
||||
"monolog/monolog": "~1.3",
|
||||
"phpunit/phpunit": "3.7.*"
|
||||
},
|
||||
"suggest": {
|
||||
"monolog/monolog": "The recommended logging library to use with Propel."
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Propel": "src/"
|
||||
}
|
||||
},
|
||||
"bin": [
|
||||
"bin/propel"
|
||||
],
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.0-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
70
core/vendor/propel/propel/features/bootstrap/FeatureContext.php
vendored
Normal file
70
core/vendor/propel/propel/features/bootstrap/FeatureContext.php
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
use Behat\Behat\Context\BehatContext;
|
||||
use Behat\Gherkin\Node\PyStringNode;
|
||||
|
||||
class FeatureContext extends BehatContext
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $workingDirectory;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $platform;
|
||||
|
||||
/**
|
||||
* Initializes context.
|
||||
* Every scenario gets it's own context object.
|
||||
*
|
||||
* @param array $parameters context parameters (set them up through behat.yml)
|
||||
*/
|
||||
public function __construct(array $parameters)
|
||||
{
|
||||
// Initialize your context here
|
||||
$this->workingDirectory = sys_get_temp_dir();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^a platform is "([^"]*)"$/
|
||||
*/
|
||||
public function aPlatformIs($platform)
|
||||
{
|
||||
$this->platform = $platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^I have XML schema:$/
|
||||
*/
|
||||
public function iHaveXmlSchema(PyStringNode $string)
|
||||
{
|
||||
file_put_contents($this->workingDirectory . '/schema.xml', $string->getRaw());
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^I generate SQL$/
|
||||
*/
|
||||
public function iGenerateSql()
|
||||
{
|
||||
exec(sprintf('bin/propel sql:build --platform=%s --input-dir=%s --output-dir=%s',
|
||||
$this->platform,
|
||||
$this->workingDirectory,
|
||||
$this->workingDirectory
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^it should contain:$/
|
||||
*/
|
||||
public function itShouldContain(PyStringNode $string)
|
||||
{
|
||||
$sql = file_get_contents($this->workingDirectory . '/behat_table.sql');
|
||||
|
||||
if (empty($sql) || !preg_match(sprintf('/%s/', preg_quote($string->getRaw())), $sql)) {
|
||||
$this->printDebug($sql);
|
||||
throw new Exception('Content not found');
|
||||
}
|
||||
}
|
||||
}
|
||||
18
core/vendor/propel/propel/features/table.feature
vendored
Normal file
18
core/vendor/propel/propel/features/table.feature
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
Feature: Table
|
||||
In order to map my business objects to the database
|
||||
As a developer
|
||||
I need to be able to describe a schema
|
||||
|
||||
Scenario: Successfully created a table
|
||||
Given a platform is "MysqlPlatform"
|
||||
And I have XML schema:
|
||||
"""
|
||||
<database name="behat_table">
|
||||
<table name="a_table"></table>
|
||||
</database>
|
||||
"""
|
||||
When I generate SQL
|
||||
Then it should contain:
|
||||
"""
|
||||
CREATE TABLE `a_table`
|
||||
"""
|
||||
35
core/vendor/propel/propel/phpunit.xml.dist
vendored
Normal file
35
core/vendor/propel/propel/phpunit.xml.dist
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false"
|
||||
syntaxCheck="false"
|
||||
bootstrap="tests/bootstrap.php"
|
||||
>
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="Propel2 Test Suite">
|
||||
<directory>./tests/Propel/Tests/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory>./src/Propel/</directory>
|
||||
<exclude>
|
||||
<directory>./bin</directory>
|
||||
<directory>./documentation</directory>
|
||||
<directory>./features</directory>
|
||||
<directory>./resources</directory>
|
||||
<directory>./src/Propel/Generator/Behavior/*/templates/</directory>
|
||||
<directory>./tests</directory>
|
||||
<directory>./tools</directory>
|
||||
<directory>./vendor</directory>
|
||||
</exclude>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
||||
54
core/vendor/propel/propel/pom.xml.dist
vendored
Normal file
54
core/vendor/propel/propel/pom.xml.dist
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.propelorm.propel2</groupId>
|
||||
<artifactId>Propel2</artifactId>
|
||||
<name>The Propel2 PHP ORM</name>
|
||||
<version>2.0.0-DEV</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>src</sourceDirectory>
|
||||
<testSourceDirectory>tests</testSourceDirectory>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
|
||||
<!-- General settings -->
|
||||
|
||||
<sonar.language>php</sonar.language>
|
||||
|
||||
<!-- Database settings -->
|
||||
<!--
|
||||
<sonar.jdbc.url>
|
||||
<![CDATA[jdbc:mysql://127.0.0.1:3306/sonar?useUnicode=true&characterEncoding=utf8]]>
|
||||
</sonar.jdbc.url>
|
||||
<sonar.jdbc.driverClassName> com.mysql.jdbc.Driver</sonar.jdbc.driverClassName>
|
||||
<sonar.jdbc.username>sonar</sonar.jdbc.username>
|
||||
<sonar.jdbc.password>sonar</sonar.jdbc.password>
|
||||
|
||||
-->
|
||||
|
||||
<!-- Automated tools settings -->
|
||||
|
||||
<sonar.dynamicAnalysis>true</sonar.dynamicAnalysis>
|
||||
|
||||
<sonar.phpDepend.shouldRun>true</sonar.phpDepend.shouldRun>
|
||||
|
||||
<sonar.phpPmd.shouldRun>true</sonar.phpPmd.shouldRun>
|
||||
<sonar.phpPmd.analyzeOnly>false</sonar.phpPmd.analyzeOnly>
|
||||
|
||||
<sonar.phpCodesniffer.shouldRun>true</sonar.phpCodesniffer.shouldRun>
|
||||
|
||||
<sonar.phpUnit.analyze.test.directory>false</sonar.phpUnit.analyze.test.directory>
|
||||
<sonar.phpUnit.skip>true</sonar.phpUnit.skip>
|
||||
<!--
|
||||
<sonar.phpUnit.coverage.skip>true</sonar.phpUnit.coverage.skip>
|
||||
<sonar.phpUnit.mainTestClass>/source/tests/AllTests2.php</sonar.phpUnit.mainTestClass>
|
||||
-->
|
||||
|
||||
<sonar.phpcpd.shouldRun>true</sonar.phpcpd.shouldRun>
|
||||
<sonar.phpcpd.excludes>tests</sonar.phpcpd.excludes>
|
||||
|
||||
</properties>
|
||||
</project>
|
||||
169
core/vendor/propel/propel/resources/dtd/database.dtd
vendored
Normal file
169
core/vendor/propel/propel/resources/dtd/database.dtd
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
<!--
|
||||
Propel XML database schema DTD
|
||||
$Id: database.dtd,v 1.7 2005/03/30 11:38:18 hlellelid Exp $
|
||||
|
||||
This is based very closely on the schema DTD for Torque, but
|
||||
some differences do exist.
|
||||
-->
|
||||
|
||||
<!--
|
||||
|
||||
defaultPhpNamingMethod determines how a table or column name,
|
||||
from the name attribute in the xml database file, is converted to a
|
||||
PHP class or method name.
|
||||
|
||||
nochange - indicates not change is performed.
|
||||
underscore - Underscores are removed, First letter is
|
||||
capitalized, first letter after an underscore
|
||||
is capitalized, the rest of the letters are
|
||||
converted to lowercase.
|
||||
phpname - same as underscore, but no letters are converted
|
||||
to lowercase.
|
||||
-->
|
||||
|
||||
<!ELEMENT database (external-schema*, table+, behavior*)>
|
||||
<!ATTLIST database
|
||||
name CDATA #IMPLIED
|
||||
defaultIdMethod (native|none) "none"
|
||||
package CDATA #IMPLIED
|
||||
schema CDATA #IMPLIED
|
||||
namespace CDATA #IMPLIED
|
||||
baseClass CDATA #IMPLIED
|
||||
defaultPhpNamingMethod (nochange|underscore|phpname) "underscore"
|
||||
heavyIndexing (true|false) "false"
|
||||
tablePrefix CDATA #IMPLIED
|
||||
defaultStringFormat CDATA #IMPLIED
|
||||
xmlns:xsi CDATA #IMPLIED
|
||||
xsi:noNamespaceSchemaLocation CDATA #IMPLIED
|
||||
>
|
||||
|
||||
<!ELEMENT external-schema EMPTY>
|
||||
<!ATTLIST external-schema
|
||||
filename CDATA #REQUIRED
|
||||
>
|
||||
|
||||
<!--
|
||||
note: the interface="true", requires that useManagers=true in the
|
||||
properties file.
|
||||
-->
|
||||
<!ELEMENT table (column+,(foreign-key|index|unique|id-method-parameter|behavior|vendor)*)>
|
||||
<!ATTLIST table
|
||||
name CDATA #REQUIRED
|
||||
phpName CDATA #IMPLIED
|
||||
idMethod (native|autoincrement|sequence|none|null) "null"
|
||||
skipSql (true|false) "false"
|
||||
readOnly (true|false) "false"
|
||||
abstract (true|false) "false"
|
||||
isCrossRef (true|false) "false"
|
||||
package CDATA #IMPLIED
|
||||
schema CDATA #IMPLIED
|
||||
namespace CDATA #IMPLIED
|
||||
baseClass CDATA #IMPLIED
|
||||
alias CDATA #IMPLIED
|
||||
interface CDATA #IMPLIED
|
||||
phpNamingMethod (nochange|underscore|phpname) #IMPLIED
|
||||
heavyIndexing (true|false) #IMPLIED
|
||||
description CDATA #IMPLIED
|
||||
defaultStringFormat CDATA #IMPLIED
|
||||
>
|
||||
|
||||
<!ELEMENT id-method-parameter EMPTY>
|
||||
<!ATTLIST id-method-parameter
|
||||
name CDATA "default"
|
||||
value CDATA #REQUIRED
|
||||
>
|
||||
|
||||
<!ELEMENT column ((inheritance|vendor)*)>
|
||||
<!ATTLIST column
|
||||
name CDATA #REQUIRED
|
||||
phpName CDATA #IMPLIED
|
||||
tableMapName CDATA #IMPLIED
|
||||
primaryKey (true|false) "false"
|
||||
required (true|false) "false"
|
||||
type
|
||||
(
|
||||
BIT | TINYINT | SMALLINT | INTEGER | BIGINT | FLOAT
|
||||
| REAL | NUMERIC | DECIMAL | CHAR | VARCHAR | LONGVARCHAR
|
||||
| DATE | TIME | TIMESTAMP | BINARY | VARBINARY | LONGVARBINARY
|
||||
| NULL | OTHER | PHP_OBJECT | DISTINCT | STRUCT | ARRAY
|
||||
| BLOB | CLOB | REF | BOOLEANINT | BOOLEANCHAR
|
||||
| DOUBLE | BOOLEAN | OBJECT | ENUM
|
||||
) "VARCHAR"
|
||||
phpType CDATA #IMPLIED
|
||||
sqlType CDATA #IMPLIED
|
||||
size CDATA #IMPLIED
|
||||
scale CDATA #IMPLIED
|
||||
default CDATA #IMPLIED
|
||||
defaultValue CDATA #IMPLIED
|
||||
defaultExpr CDATA #IMPLIED
|
||||
autoIncrement (true|false) "false"
|
||||
inheritance (single|false) "false"
|
||||
phpNamingMethod (nochange|underscore|phpname) #IMPLIED
|
||||
description CDATA #IMPLIED
|
||||
lazyLoad (true|false) "false"
|
||||
primaryString (true|false) "false"
|
||||
valueSet CDATA #IMPLIED
|
||||
>
|
||||
|
||||
<!ELEMENT inheritance EMPTY>
|
||||
<!ATTLIST inheritance
|
||||
key CDATA #REQUIRED
|
||||
class CDATA #REQUIRED
|
||||
package CDATA #IMPLIED
|
||||
extends CDATA #IMPLIED
|
||||
>
|
||||
|
||||
<!ELEMENT foreign-key (reference+, vendor*)>
|
||||
<!ATTLIST foreign-key
|
||||
foreignTable CDATA #REQUIRED
|
||||
foreignSchema CDATA #IMPLIED
|
||||
name CDATA #IMPLIED
|
||||
phpName CDATA #IMPLIED
|
||||
refPhpName CDATA #IMPLIED
|
||||
onUpdate (CASCADE|cascade|SETNULL|setnull|RESTRICT|restrict|NONE|none) "none"
|
||||
onDelete (CASCADE|cascade|SETNULL|setnull|RESTRICT|restrict|NONE|none) "none"
|
||||
skipSql (true|false) "false"
|
||||
>
|
||||
|
||||
<!ELEMENT reference EMPTY>
|
||||
<!ATTLIST reference
|
||||
local CDATA #REQUIRED
|
||||
foreign CDATA #REQUIRED
|
||||
>
|
||||
|
||||
<!ELEMENT index (index-column+)>
|
||||
<!ATTLIST index
|
||||
name CDATA #IMPLIED
|
||||
>
|
||||
|
||||
<!ELEMENT behavior (parameter+)>
|
||||
<!ATTLIST behavior
|
||||
name CDATA #IMPLIED
|
||||
>
|
||||
|
||||
<!ELEMENT index-column (vendor*)>
|
||||
<!ATTLIST index-column
|
||||
name CDATA #REQUIRED
|
||||
size CDATA #IMPLIED
|
||||
>
|
||||
|
||||
<!ELEMENT unique (unique-column+)>
|
||||
<!ATTLIST unique
|
||||
name CDATA #IMPLIED
|
||||
>
|
||||
|
||||
<!ELEMENT unique-column (vendor*)>
|
||||
<!ATTLIST unique-column
|
||||
name CDATA #REQUIRED
|
||||
>
|
||||
|
||||
<!ELEMENT vendor (parameter+)>
|
||||
<!ATTLIST vendor
|
||||
type CDATA #REQUIRED
|
||||
>
|
||||
|
||||
<!ELEMENT parameter EMPTY>
|
||||
<!ATTLIST parameter
|
||||
name CDATA #REQUIRED
|
||||
value CDATA #REQUIRED
|
||||
>
|
||||
8
core/vendor/propel/propel/resources/xsd/custom_datatypes.xsd
vendored
Normal file
8
core/vendor/propel/propel/resources/xsd/custom_datatypes.xsd
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
|
||||
<xs:simpleType name='custom_datatypes'>
|
||||
<xs:restriction base='xs:string'>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:schema>
|
||||
856
core/vendor/propel/propel/resources/xsd/database.xsd
vendored
Normal file
856
core/vendor/propel/propel/resources/xsd/database.xsd
vendored
Normal file
@@ -0,0 +1,856 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<!-- XML Schema for the Propel schema file
|
||||
An additional xml schema: custom_datatypes.xsd is
|
||||
also included. -->
|
||||
|
||||
<xs:include schemaLocation="custom_datatypes.xsd"/>
|
||||
|
||||
<xs:element name="database" type="database"/>
|
||||
|
||||
<xs:element name="vendor" type="vendor"/>
|
||||
|
||||
<xs:simpleType name="file">
|
||||
<xs:restriction base="xs:string">
|
||||
<!-- Match any relative or absolute path and file containing letters, numbers, - and _ -->
|
||||
<xs:pattern value="((\.{1,2}|[\w_-]*)/)*([\w_-]*\.?)+"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="default_datatypes">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="BIT"/>
|
||||
<xs:enumeration value="TINYINT"/>
|
||||
<xs:enumeration value="SMALLINT"/>
|
||||
<xs:enumeration value="INTEGER"/>
|
||||
<xs:enumeration value="BIGINT"/>
|
||||
<xs:enumeration value="FLOAT"/>
|
||||
<xs:enumeration value="REAL"/>
|
||||
<xs:enumeration value="NUMERIC"/>
|
||||
<xs:enumeration value="DECIMAL"/>
|
||||
<xs:enumeration value="CHAR"/>
|
||||
<xs:enumeration value="VARCHAR"/>
|
||||
<xs:enumeration value="LONGVARCHAR"/>
|
||||
<xs:enumeration value="DATE"/>
|
||||
<xs:enumeration value="TIME"/>
|
||||
<xs:enumeration value="TIMESTAMP"/>
|
||||
<xs:enumeration value="BINARY"/>
|
||||
<xs:enumeration value="VARBINARY"/>
|
||||
<xs:enumeration value="LONGVARBINARY"/>
|
||||
<xs:enumeration value="NULL"/>
|
||||
<xs:enumeration value="OTHER"/>
|
||||
<xs:enumeration value="DISTINCT"/>
|
||||
<xs:enumeration value="STRUCT"/>
|
||||
<xs:enumeration value="BLOB"/>
|
||||
<xs:enumeration value="CLOB"/>
|
||||
<xs:enumeration value="REF"/>
|
||||
<xs:enumeration value="BOOLEANINT"/>
|
||||
<xs:enumeration value="BOOLEANCHAR"/>
|
||||
<xs:enumeration value="DOUBLE"/>
|
||||
<xs:enumeration value="BOOLEAN"/>
|
||||
<xs:enumeration value="OBJECT"/>
|
||||
<xs:enumeration value="ARRAY"/>
|
||||
<xs:enumeration value="ENUM"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="datatype">
|
||||
<xs:union memberTypes="default_datatypes custom_datatypes"/>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="dbidmethod">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="native"/>
|
||||
<xs:enumeration value="none"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="tbidmethod">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="autoincrement"/>
|
||||
<xs:enumeration value="sequence"/>
|
||||
<xs:enumeration value="null"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="idmethod">
|
||||
<xs:union memberTypes="dbidmethod tbidmethod"/>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="phpnamingmethod">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="nochange"/>
|
||||
<xs:enumeration value="underscore"/>
|
||||
<xs:enumeration value="phpname"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="delete">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="cascade"/>
|
||||
<xs:enumeration value="CASCADE"/>
|
||||
<xs:enumeration value="set null"/>
|
||||
<xs:enumeration value="SET NULL"/>
|
||||
<xs:enumeration value="setnull"/>
|
||||
<xs:enumeration value="SETNULL"/>
|
||||
<xs:enumeration value="restrict"/>
|
||||
<xs:enumeration value="RESTRICT"/>
|
||||
<xs:enumeration value="none"/>
|
||||
<xs:enumeration value="NONE"/>
|
||||
<xs:enumeration value=""/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="update">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="cascade"/>
|
||||
<xs:enumeration value="CASCADE"/>
|
||||
<xs:enumeration value="set null"/>
|
||||
<xs:enumeration value="SET NULL"/>
|
||||
<xs:enumeration value="setnull"/>
|
||||
<xs:enumeration value="SETNULL"/>
|
||||
<xs:enumeration value="restrict"/>
|
||||
<xs:enumeration value="RESTRICT"/>
|
||||
<xs:enumeration value="none"/>
|
||||
<xs:enumeration value="NONE"/>
|
||||
<xs:enumeration value=""/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="rulename">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="match"/>
|
||||
<xs:enumeration value="maxLength"/>
|
||||
<xs:enumeration value="maxValue"/>
|
||||
<xs:enumeration value="minLength"/>
|
||||
<xs:enumeration value="minValue"/>
|
||||
<xs:enumeration value="notMatch"/>
|
||||
<xs:enumeration value="required"/>
|
||||
<xs:enumeration value="type"/>
|
||||
<xs:enumeration value="unique"/>
|
||||
<xs:enumeration value="validValues"/>
|
||||
<!-- the next validators don't seem to be implemented, keeping them for BC -->
|
||||
<xs:enumeration value="mask"/>
|
||||
<xs:enumeration value="class"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="inh_option">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="single"/>
|
||||
<xs:enumeration value="false"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="sql_type">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:pattern value="[\w\s\[\]\(\),\.'\-_]+"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="php_type">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:pattern value="[\w_]+"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<!-- Visibility for column accessor and mutator methods -->
|
||||
<xs:simpleType name="visibility">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="public"/>
|
||||
<xs:enumeration value="protected"/>
|
||||
<xs:enumeration value="private"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<!-- Restrict column name to letters (upper- and lowercase), numbers and the _ -->
|
||||
<xs:simpleType name="column_name">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:pattern value="[\w_]+"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<!-- Restrict php name to letters (upper- and lowercase), numbers and the _ -->
|
||||
<xs:simpleType name="php_name">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:pattern value="[\w_]+"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<!-- Restrict php class name to letters (upper- and lowercase), numbers and the _. Dot seperated -->
|
||||
<xs:simpleType name="php_class">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:pattern value="([\w_]+.?)+"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<!-- Restrict php namespaces name to letters (upper- and lowercase), numbers and the backslash Dot seperated -->
|
||||
<xs:simpleType name="php_namespace">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:pattern value="(\\?[\w_]+)+"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<!-- Restrict table name to letters (upper- and lowercase), numbers and the _ -->
|
||||
<xs:simpleType name="table_name">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:pattern value="[\w_]+"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<!-- Restrict schema name to letters (upper- and lowercase), numbers and the _ -->
|
||||
<xs:simpleType name="schema_name">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:pattern value="[\w_]+"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<!-- Restrict index name to letters (upper- and lowercase), numbers and the _ -->
|
||||
<xs:simpleType name="index_name">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:pattern value="[\w_]+"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<!-- Restrict foreign column name to letters (upper- and lowercase), numbers and the _ -->
|
||||
<xs:simpleType name="foreign_name">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:pattern value="[\w_]+"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:complexType name="parameter">
|
||||
<xs:attribute name="name" type="xs:string" use="required"/>
|
||||
<xs:attribute name="value" type="xs:string" use="required"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="validator">
|
||||
<xs:sequence>
|
||||
<xs:element name="rule" type="rule" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="column" type="column_name" use="required"/>
|
||||
<xs:attribute name="translate" type="xs:string" use="optional"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="vendor">
|
||||
<xs:sequence>
|
||||
<xs:element name="parameter" type="parameter" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="type" use="required"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="rule">
|
||||
<xs:attribute name="name" type="rulename" use="required"/>
|
||||
<xs:attribute name="value" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="size" type="xs:positiveInteger" use="optional"/>
|
||||
<xs:attribute name="message" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="class" type="xs:string" use="optional"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="id-method-parameter">
|
||||
<xs:attribute name="name" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="value" type="xs:string" use="required"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="index">
|
||||
<xs:choice maxOccurs="unbounded">
|
||||
<xs:element name="index-column" type="index-column" minOccurs="1" maxOccurs="unbounded"/>
|
||||
<xs:element ref="vendor" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:choice>
|
||||
<xs:attribute name="name" type="index_name" use="optional"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="unique">
|
||||
<xs:choice maxOccurs="unbounded">
|
||||
<xs:element name="unique-column" type="unique-column" minOccurs="1" maxOccurs="unbounded"/>
|
||||
<xs:element ref="vendor" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:choice>
|
||||
<xs:attribute name="name" type="index_name" use="optional"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="index-column">
|
||||
<xs:sequence>
|
||||
<xs:element ref="vendor" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="name" type="column_name" use="required"/>
|
||||
<xs:attribute name="size" type="xs:positiveInteger" use="optional"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="unique-column">
|
||||
<xs:sequence>
|
||||
<xs:element ref="vendor" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="name" type="column_name" use="required"/>
|
||||
<xs:attribute name="size" type="xs:positiveInteger" use="optional"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="inheritance">
|
||||
<xs:attribute name="key" type="xs:string" use="required"/>
|
||||
<xs:attribute name="class" type="xs:string" use="required"/>
|
||||
<xs:attribute name="package" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="extends" type="xs:string" use="optional"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="reference">
|
||||
<xs:attribute name="local" type="column_name" use="required"/>
|
||||
<xs:attribute name="foreign" type="column_name" use="required"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="behavior">
|
||||
<xs:choice maxOccurs="unbounded">
|
||||
<xs:element name="parameter" type="parameter" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:choice>
|
||||
<xs:attribute name="name" type="xs:string" use="required"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="column">
|
||||
<xs:choice maxOccurs="unbounded">
|
||||
<xs:element name="inheritance" type="inheritance" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element ref="vendor" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:choice>
|
||||
<xs:attribute name="name" type="column_name" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
The name of the column as it appears in the database.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="phpName" type="php_name" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Name used in PHP code to reference this column (in getters, setters, etc.). Defaults to the name transformed by the phpNamingMethod, which defaults to a CamelCase converter. So by default, a column named 'author_id' receives 'AuthorId' as phpName.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="tableMapName" type="php_class" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Name used for the class constant corresponding to this column in PHP code. Defaults to the uppercase name, so a column named 'author_id' receives 'AUTHOR_ID' as tableMapName.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="prefix" type="column_name" use="optional"/>
|
||||
<xs:attribute name="accessorVisibility" type="visibility" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Visibility for the column accessor method. 'public' by default, also accepts 'protected' and 'private'.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="mutatorVisibility" type="visibility" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Visibility for the column mutator method. 'public' by default, also accepts 'protected' and 'private'.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="primaryKey" type="xs:boolean" default="false">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Set to true to add a primary key on this column.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="required" type="xs:boolean" default="false">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Set to true to forbid NULL values.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="type" type="datatype" default="VARCHAR">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Any of the Propel supported data types. These types are database-agnostic, and converted to the native database type according to the connection.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="sqlType" type="sql_type" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Native database column type.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="phpType" type="php_type" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
PHP type for te column in PHP code. This column's setter uses type casting with the set php_type; besides, generated phpDoc in the model classes use this attribute for code completion.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="size" type="xs:nonNegativeInteger" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Numeric length of the column.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="scale" type="xs:nonNegativeInteger" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Digits after decimal place
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="default" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Synonym for defaultValue
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="defaultValue" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
The default value that the object will have for this column in the PHP instance after creating a "new Object". This value is always interpreted as a string. See defaultExpr for setting an SQL function as a default value.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="defaultExpr" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
The default value for this column as expressed in SQL. This value is used solely for the "sql" target which builds your database from the schema.xml file. The defaultExpr is the SQL expression used as the "default" for the column.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="autoIncrement" type="xs:boolean" default="false"/>
|
||||
<xs:attribute name="inheritance" type="inh_option" default="false"/>
|
||||
<xs:attribute name="phpNamingMethod" type="phpnamingmethod" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Name of the method used to transform the column name into a phpName. Defaults to 'clean', which Removes any character that is not a letter or a number and capitilizes the first letter of the name, the first letter of each alphanumeric block, and converts the rest of the letters to lowercase. Possible values: any of the PhpNameGenerator CONV_METHOD_XXX constants (clean, underscore, phpName, nochange).
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="description" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
A text description of the column. It gets added to the SQL CREATE table as a comment, and appears in the phpDoc bloc of the related getter and setter methods in the ActiveRecord class.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="lazyLoad" type="xs:boolean" default="false">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Set to true to skip this column by default during hydration. That means that this column will be hydrated on demand, using a supplementary query. Mostly useful for LOB columns.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="primaryString" type="xs:boolean" default="false">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
A column defined as primary string serves as default value for a `__toString()` method in the generated Propel object.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="valueSet" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
The list of values for an ENUM column, separated by commas
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="foreign-key">
|
||||
<xs:choice maxOccurs="unbounded">
|
||||
<xs:element name="reference" type="reference" minOccurs="1" maxOccurs="unbounded">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
A reference between a local and a foreign column. Composite foreign keys can have several references.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element ref="vendor" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:choice>
|
||||
<xs:attribute name="foreignTable" type="table_name" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
The other table name
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="foreignSchema" type="schema_name" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
The other schema name
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="name" type="foreign_name" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Name for this foreign key
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="phpName" type="php_name" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Name for the foreign object in methods generated in this class.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="refPhpName" type="php_name" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Name for this object in methods generated in the foreign class
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="defaultJoin" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
This affects the default join type used in the generated `joinXXX()` methods in the model query class. Propel uses an INNER JOIN for foreign keys attached to a required column, and a LEFT JOIN for foreign keys attached to a non-required column, but you can override this in the foreign key element.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="onDelete" type="delete" default="none"/>
|
||||
<xs:attribute name="onUpdate" type="update" default="none"/>
|
||||
<xs:attribute name="skipSql" type="xs:boolean" default="false">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Instructs Propel not to generate DDL SQL for the specified foreign key. This can be used to support relationships in the model without an actual foreign key.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="external-schema">
|
||||
<xs:attribute name="filename" type="file" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
The (absolute or relative to this schema dir name) path to the external schema file.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="table">
|
||||
<xs:choice maxOccurs="unbounded">
|
||||
|
||||
<xs:element name="column" type="column" maxOccurs="unbounded">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
A column of the table
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
|
||||
<xs:element name="foreign-key" type="foreign-key" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
A foreign key on one or several columns in this table, referencing a foreign table
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
|
||||
<!-- TODO: to be removed? The Table model class does not support this option -->
|
||||
<xs:element name="index" type="index" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
An index on one or several columns of the current table
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
|
||||
<!-- TODO: to be removed? The Table model class does not support this option -->
|
||||
<xs:element name="unique" type="unique" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
A unique index on one or several columns of the current table
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
|
||||
<xs:element name="id-method-parameter" type="id-method-parameter" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
If you are using a database that uses sequences for auto-increment columns (e.g. PostgreSQL or Oracle), you can customize the name of the sequence using this tag
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
|
||||
<!-- TODO: to be removed? Are validators still supported in Propel 2? -->
|
||||
<xs:element name="validator" type="validator" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
A validator to be executed on a given column at runtime
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
|
||||
<xs:element name="behavior" type="behavior" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
A behavior to be added to the current table. Can modify the table structure, as well as modify the runtime code of the generated Model objects linked to this table. Bundled behaviors include alternative_coding_standards, auto_add_pk, timestampable, sluggable, sortable, nested_set, query_cache, and concrete_inheritance.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
|
||||
<xs:element ref="vendor" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
table attributes specific to a database vendor. Only supports MySQL specific table attributes for now (Charset, Collate, Checksum, Pack_keys, Delay_key_write).
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
|
||||
</xs:choice>
|
||||
<xs:attribute name="name" type="table_name" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
The name of the table as it appears in the database.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="schema" type="schema_name" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
The table's schema for RDBMs supporting multiple schemas per database.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="phpName" type="php_class" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
The name of the ActiveRecord class generated for this table. Defaults to the name transformed by the phpNamingMethod, which defaults to a CamelCase converter. So by default, a table named 'foo_author' receives 'FooAuthor' as phpName.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="namespace" type="php_namespace" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
The PHP 5.3 namespace to use for the generated model classes.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<!-- TODO: to be removed? Is this really supported? -->
|
||||
<xs:attribute name="columnPrefix" type="column_name" use="optional"/>
|
||||
<xs:attribute name="defaultAccessorVisibility" type="visibility" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Default visibility for column accessor methods. 'public' by default, also accepts 'protected' and 'private'.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="defaultMutatorVisibility" type="visibility" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Default visibility for column mutator methods. 'public' by default, also accepts 'protected' and 'private'.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="idMethod" type="idmethod" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Id method to use for auto-increment columns.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="allowPkInsert" type="xs:boolean" default="false" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Can be used if you want to define the primary key of a new object being inserted. By default if idMethod is "native", Propel would throw an exception. However, in some cases this feature is useful, for example if you do some replication of data in an master-master environment.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="skipSql" type="xs:boolean" default="false">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Instructs Propel not to generate DDL SQL for the specified table. This can be used together with readOnly for supporting VIEWS in Propel
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="readOnly" type="xs:boolean" default="false">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Suppresses the mutator/setter methods, save() and delete() methods.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="abstract" type="xs:boolean" default="false">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Whether the generated stub class will be abstract (e.g. if you're using inheritance)
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="baseClass" type="php_class" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Allows you to specify a class that the generated Propel objects should extend (in place of propel.om.BaseObject)
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="alias" type="table_name" use="optional"/>
|
||||
<xs:attribute name="package" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Specifies the "package" for the generated classes. Classes are created in subdirectories according to the package attribute value.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="interface" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="phpNamingMethod" type="phpnamingmethod" use='optional'>
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Name of the method used to transform the table name into a phpName. Defaults to 'clean', which Removes any character that is not a letter or a number and capitilizes the first letter of the name, the first letter of each alphanumeric block, and converts the rest of the letters to lowercase. Possible values: any of the PhpNameGenerator CONV_METHOD_XXX constants (clean, underscore, phpName, nochange).
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="heavyIndexing" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Adds indexes for each component of the primary key (when using composite primary keys)
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="description" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
A text description of the table. It gets added to the SQL CREATE table as a comment, and appears in the phpDoc bloc of the related ActiveRecord class.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="reloadOnInsert" type="xs:boolean" default="false">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Indicate that the object should be reloaded from the database when an INSERT is performed. This is useful if you have triggers (or other server-side functionality like column default expressions) that alters the database row on INSERT.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="reloadOnUpdate" type="xs:boolean" default="false">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Indicate that the object should be reloaded from the database when an UPDATE is performed. This is useful if you have triggers (or other server-side functionality like column default expressions) that alters the database row on UPDATE.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="isCrossRef" type="xs:boolean" default="false">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Set to true if the current table is a cross-reference table in a many-to-many relationship to allow generation of getter and setter in each of the tables of the relationship.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="defaultStringFormat" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
The default format used to convert objects based on this table to strings. Propel supports by default the 'XML', 'YAML', 'JSON', and 'CSV' formats, but custom formats are also possible.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="database">
|
||||
<xs:choice maxOccurs="unbounded">
|
||||
<xs:element name="external-schema" type="external-schema" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Embed an external schema file into the current schema. Accepts absolute and relative schema file paths.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="table" type="table" minOccurs="1" maxOccurs="unbounded">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
A table using the database connection.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="behavior" type="behavior" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Behavior to be applied to all the database tables
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:choice>
|
||||
<xs:attribute name="name" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
The name of the table in the database. Propel advocates the use of singular table names.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="defaultIdMethod" type="dbidmethod" default="none">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Default id method to use for auto-increment columns
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="defaultAccessorVisibility" type="visibility" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Default visibility for column accessor methods. 'public' by default, also accepts 'protected' and 'private'.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="defaultMutatorVisibility" type="visibility" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Default visibility for column mutator methods. 'public' by default, also accepts 'protected' and 'private'.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="package" type="file" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Specifies the "package" for the generated classes. Classes are created in subdirectories according to the package attribute value.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="namespace" type="php_namespace" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
The PHP 5.3 namespace to use for the generated model classes of the database. Can be overridden on a per-table basis.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="schema" type="schema_name" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Specify a schema for the tables in this database. Useful for RDBMs which support multiple schemas per database.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="baseClass" type="php_class" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Allows to specify a default base class that all generated Propel objects should extend (in place of propel.om.BaseObject)
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="defaultPhpNamingMethod" type="phpnamingmethod" default="underscore">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
The default naming method to use in this database.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="heavyIndexing" type="xs:boolean" default="false">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Adds indexes for each component of the primary key (when using composite primary keys)
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="tablePrefix" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
Adds a prefix to all the SQL table names
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="defaultStringFormat" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation xml:lang="en">
|
||||
The default format used to convert objects based on this database to strings. Propel supports by default the 'XML', 'YAML', 'JSON', and 'CSV' formats, but custom formats are also possible.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
||||
269
core/vendor/propel/propel/resources/xsl/database.xsl
vendored
Normal file
269
core/vendor/propel/propel/resources/xsl/database.xsl
vendored
Normal file
@@ -0,0 +1,269 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!DOCTYPE xsl:stylesheet [<!ENTITY nbsp " ">]>
|
||||
|
||||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||
<!--
|
||||
XSL Stylesheet to normalize a database schema
|
||||
-->
|
||||
|
||||
<!--
|
||||
Output indented UTF 8 XML
|
||||
-->
|
||||
<xsl:output method="xml" indent="yes" encoding="UTF-8" />
|
||||
|
||||
<!--
|
||||
Matches root database node, the only allowed root node
|
||||
|
||||
Starts the normalization process
|
||||
-->
|
||||
<xsl:template match='/database'>
|
||||
<database>
|
||||
<xsl:if test='not(boolean(@defaultIdMethod))'>
|
||||
<xsl:attribute name='defaultIdMethod'>native</xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:if test='not(boolean(@defaultPhpNamingMethod))'>
|
||||
<xsl:attribute name='defaultPhpNamingMethod'>underscore</xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:if test='not(boolean(@heavyIndexing))'>
|
||||
<xsl:attribute name='heavyIndexing'>false</xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:apply-templates select='@*'/>
|
||||
<xsl:apply-templates select='external-schema'/>
|
||||
<xsl:apply-templates select='table'/>
|
||||
<xsl:apply-templates select='behavior'/>
|
||||
</database>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Normalizes any defaultPhpNamingMethod attribute by making it lowercase
|
||||
-->
|
||||
<xsl:template match='@defaultPhPNamingMethod'>
|
||||
<xsl:attribute name='defaultPhPNamingMethod'><xsl:value-of select='translate(., "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz")'/></xsl:attribute>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Normalizes any onDelete attribute by making it lowercase, or none if it is empty (makes onDelete='' act the same as onDelete='none')
|
||||
-->
|
||||
<xsl:template match='@onDelete' name='onDelete'>
|
||||
<xsl:choose>
|
||||
<xsl:when test='.=""'>
|
||||
<xsl:attribute name='onDelete'>none</xsl:attribute>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:attribute name='onDelete'><xsl:value-of select='translate(., "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz")'/></xsl:attribute>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Handle OnDelete the same as onDelete
|
||||
-->
|
||||
<xsl:template match='@OnDelete'>
|
||||
<xsl:call-template name='onDelete'/>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Normalizes any onUpdate attribute by making it lowercase, or none if it is empty (similar to onDelete)
|
||||
-->
|
||||
<xsl:template match='@onUpdate' name='onUpdate'>
|
||||
<xsl:choose>
|
||||
<xsl:when test='.=""'>
|
||||
<xsl:attribute name='onUpdate'>none</xsl:attribute>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:attribute name='onUpdate'><xsl:value-of select='translate(., "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz")'/></xsl:attribute>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Handle OnUpdate the same as onUpdate
|
||||
-->
|
||||
<xsl:template match='@OnUpdate'>
|
||||
<xsl:call-template name='onUpdate'/>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Tranlate IdMethod attribute to idMethod attribute
|
||||
-->
|
||||
<xsl:template match='@IdMethod'>
|
||||
<xsl:attribute name='idMethod'><xsl:value-of select='.'/></xsl:attribute>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Just copy any attribute
|
||||
-->
|
||||
<xsl:template match='@*' priority='-1'>
|
||||
<xsl:copy-of select='.'/>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Normalize a table, add some attribute with default values if ommitted and normalize all attribute and childnodes
|
||||
-->
|
||||
<xsl:template match='table'>
|
||||
<table>
|
||||
<xsl:if test='not(boolean(@skipSql))'>
|
||||
<xsl:attribute name='skipSql'>false</xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:if test='not(boolean(@abstract))'>
|
||||
<xsl:attribute name='abstract'>false</xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:apply-templates select='@*'/>
|
||||
<xsl:apply-templates select='column'/>
|
||||
<xsl:apply-templates select='foreign-key'/>
|
||||
<xsl:apply-templates select='index'/>
|
||||
<xsl:apply-templates select='unique'/>
|
||||
<xsl:apply-templates select='id-method-parameter'/>
|
||||
<xsl:apply-templates select='vendor'/>
|
||||
<xsl:apply-templates select='behavior'/>
|
||||
</table>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Normalize a foreign-key, add some attribute with default values if ommitted and normalize all attribute and childnodes
|
||||
-->
|
||||
<xsl:template match='foreign-key'>
|
||||
<foreign-key>
|
||||
<xsl:if test='not(boolean(@onDelete)) and not(boolean(@OnDelete))'>
|
||||
<xsl:attribute name='onDelete'>none</xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:if test='not(boolean(@onUpdate)) and not(boolean(@OnUpdate))'>
|
||||
<xsl:attribute name='onUpdate'>none</xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:apply-templates select='@*'/>
|
||||
<xsl:apply-templates select='reference'/>
|
||||
<xsl:apply-templates select='vendor'/>
|
||||
</foreign-key>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Just copy the index node with attributes and add the index-column
|
||||
-->
|
||||
<xsl:template match='index'>
|
||||
<index>
|
||||
<xsl:apply-templates select='@*'/>
|
||||
<xsl:apply-templates select='index-column'/>
|
||||
</index>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Just copy the unique node with attributes and add the unique-column
|
||||
-->
|
||||
<xsl:template match='unique'>
|
||||
<unique>
|
||||
<xsl:apply-templates select='@*'/>
|
||||
<xsl:apply-templates select='unique-column'/>
|
||||
</unique>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Just copy the behavior node with attributes and add the param
|
||||
-->
|
||||
<xsl:template match='behavior'>
|
||||
<behavior>
|
||||
<xsl:apply-templates select='@*'/>
|
||||
<xsl:apply-templates select='parameter'/>
|
||||
</behavior>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!--
|
||||
Just copy the unique-column node with attributes and add the vendor node
|
||||
-->
|
||||
<xsl:template match='unique-column'>
|
||||
<unique-column>
|
||||
<xsl:apply-templates select='@*'/>
|
||||
<xsl:apply-templates select='vendor'/>
|
||||
</unique-column>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Just copy the index-column node with attributes and add the vendor node
|
||||
-->
|
||||
<xsl:template match='index-column'>
|
||||
<index-column>
|
||||
<xsl:apply-templates select='@*'/>
|
||||
<xsl:apply-templates select='vendor'/>
|
||||
</index-column>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Add default name to id-method-parameter (if none) and copy its attributes
|
||||
-->
|
||||
<xsl:template match='id-method-parameter'>
|
||||
<id-method-parameter>
|
||||
<xsl:if test='not(boolean(@name))'>
|
||||
<xsl:attribute name='name'>default</xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:apply-templates select='@*'/>
|
||||
</id-method-parameter>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Strip all childnodes (if any) from a parameter node
|
||||
-->
|
||||
<xsl:template match='parameter'>
|
||||
<parameter>
|
||||
<xsl:apply-templates select='@*'/>
|
||||
</parameter>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Just copy the vendor node with attributes and add the parameter node
|
||||
-->
|
||||
<xsl:template match='vendor'>
|
||||
<vendor>
|
||||
<xsl:apply-templates select='@*'/>
|
||||
<xsl:apply-templates select='parameter'/>
|
||||
</vendor>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Strip all childnodes from an inheritance node
|
||||
-->
|
||||
<xsl:template match='inheritance'>
|
||||
<inheritance>
|
||||
<xsl:apply-templates select='@*'/>
|
||||
</inheritance>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Normalize a column node, add default values for missing attributes and copy the content
|
||||
-->
|
||||
<xsl:template match='column'>
|
||||
<column>
|
||||
<xsl:if test='not(boolean(@primaryKey))'>
|
||||
<xsl:attribute name='primaryKey'>false</xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:if test='not(boolean(@required))'>
|
||||
<xsl:attribute name='required'>false</xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:if test='not(boolean(@type))'>
|
||||
<xsl:attribute name='type'>VARCHAR</xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:if test='not(boolean(@autoIncrement))'>
|
||||
<xsl:attribute name='autoIncrement'>false</xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:if test='not(boolean(@lazyLoad))'>
|
||||
<xsl:attribute name='lazyLoad'>false</xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:if test='@type = "VARCHAR" and not(boolean(@sqlType)) and not(boolean(@size))'>
|
||||
<xsl:attribute name='size'>255</xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:apply-templates select='@*'/>
|
||||
<xsl:apply-templates select='inheritance'/>
|
||||
<xsl:apply-templates select='vendor'/>
|
||||
</column>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
Strip all childnodes from an reference node
|
||||
-->
|
||||
<xsl:template match='reference'>
|
||||
<reference>
|
||||
<xsl:apply-templates select='@*'/>
|
||||
</reference>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
||||
381
core/vendor/propel/propel/resources/xsl/dbd2propel.xsl
vendored
Normal file
381
core/vendor/propel/propel/resources/xsl/dbd2propel.xsl
vendored
Normal file
@@ -0,0 +1,381 @@
|
||||
<?xml version="1.0"?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
|
||||
<xsl:strip-space elements="*"/>
|
||||
|
||||
<!--
|
||||
DB Designer XML to Propel Schema XML
|
||||
|
||||
==== Author: Jonathan Graham <jkgraham@gmail.com>
|
||||
==== Version: 0.5 (2008-01-25) (http://blog.tooleshed.com/?p=6)
|
||||
==== Description:
|
||||
This XSL will transform a DB Designer 4 database model XML file into a
|
||||
Propel database schema file. This allows you to design your database
|
||||
model using DB Designer 4 (models are saved in XML format) and then
|
||||
easily create the Propel database schema file.
|
||||
|
||||
The PROPEL properties that this XSL will translate are listed below.
|
||||
|
||||
TABLE: name, description
|
||||
COLUMN: name, primaryKey, required, type, size, scale, default, autoIncrement, description
|
||||
FOREIGN-KEY: foreignTable, name, onDelete
|
||||
REFERENCE: local, foreign
|
||||
INDEX: index (not related to FK), unique, fulltext
|
||||
|
||||
==== Usage:
|
||||
- Simply feed this XSL into your favorite XSLT engine along with your DB Designer
|
||||
XML model. The resulting output is a Propel database schema XML.
|
||||
|
||||
==== Collaboration:
|
||||
Peter Banik <peter@froggle.org> - UNIQUE TAG
|
||||
Benedicto Franco Jr. - MULTIPLE FOREIGN KEY, DATABASE NAME
|
||||
Martin Kreidenweis <martin@kreidenweis.com> - Bug fixes, INDEX
|
||||
Michiel Hakvoort - onDelete
|
||||
Michel D'HOOGE - FULLTEXT
|
||||
Oleg Marchuk <kingoleg@mail.ru> - version 0.5
|
||||
|
||||
==== Software:
|
||||
Propel: http://propel.phpdb.org/
|
||||
DB Designer 4: http://www.fabforce.net/dbdesigner4/
|
||||
|
||||
==== Copyright (c) 2004-2006, Jonathan Graham
|
||||
Licensed under the GNU Lesser General Public License (LGPL) - http://www.gnu.org/copyleft/lgpl.html.
|
||||
|
||||
==== Change Log
|
||||
version 0.1 (2004-11-08) - initial version
|
||||
version 0.2 (2006-10-18) - Added Peter and Benedicto's updates.
|
||||
version 0.3 (2006-11-05) - added non-unique-INDEXes and onDelete
|
||||
version 0.4 (2006-11-13) - added support for index names and FULLTEXT indexes, changed license to LGPL
|
||||
version 0.5 (2008-01-25) - added ENUM, GEOMETRY as BLOB, scale for DECIMAL; fixed size in ENUM and spaces in relation names
|
||||
|
||||
-->
|
||||
|
||||
<!-- ============================================================ DATABASE template -->
|
||||
<xsl:template match="/">
|
||||
<database defaultIdMethod="native">
|
||||
<xsl:attribute name="name">
|
||||
<xsl:value-of select="/DBMODEL/SETTINGS/GLOBALSETTINGS/@ModelName"/>
|
||||
</xsl:attribute>
|
||||
<xsl:apply-templates />
|
||||
</database>
|
||||
</xsl:template>
|
||||
|
||||
<!-- ============================================================ TABLES template -->
|
||||
<xsl:template match="/DBMODEL/METADATA/TABLES/TABLE">
|
||||
<table>
|
||||
<xsl:attribute name="name">
|
||||
<xsl:value-of select="@Tablename"/>
|
||||
</xsl:attribute>
|
||||
<xsl:if test="@Comments != ''">
|
||||
<xsl:attribute name="description">
|
||||
<xsl:value-of select="@Comments" />
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:apply-templates />
|
||||
</table>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!-- ============================================================ COLUMNS template -->
|
||||
<xsl:template match="COLUMNS/COLUMN">
|
||||
<column>
|
||||
<!-- get data type -->
|
||||
<xsl:variable name="datatype">
|
||||
<xsl:call-template name="get_datatype">
|
||||
<xsl:with-param name="id"><xsl:value-of select="@idDatatype"/></xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:variable>
|
||||
|
||||
<!-- remove parens from datatypeparams -->
|
||||
<xsl:variable name="dtpclean">
|
||||
<xsl:call-template name="clean_dataparams">
|
||||
<xsl:with-param name="dtp"><xsl:value-of select="@DatatypeParams"/></xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:variable>
|
||||
|
||||
<!-- ==== name ==== -->
|
||||
<xsl:attribute name="name">
|
||||
<xsl:value-of select="@ColName"/>
|
||||
</xsl:attribute>
|
||||
|
||||
<!-- ==== type ==== -->
|
||||
<xsl:attribute name="type">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$datatype = 'ENUM'">
|
||||
<xsl:value-of select="'CHAR'" />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="$datatype"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:attribute>
|
||||
|
||||
<xsl:if test="$dtpclean != ''">
|
||||
<!-- ==== size ==== -->
|
||||
<xsl:attribute name="size">
|
||||
<xsl:call-template name="get_datasize">
|
||||
<xsl:with-param name="dtpc"><xsl:value-of select="$dtpclean"/></xsl:with-param>
|
||||
<xsl:with-param name="dtype"><xsl:value-of select="$datatype"/></xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:attribute>
|
||||
|
||||
<xsl:if test="contains('FLOAT,DOUBLE,DECIMAL',$datatype)">
|
||||
<!-- ==== scale ==== -->
|
||||
<xsl:attribute name="scale">
|
||||
<xsl:value-of select="substring-after($dtpclean,',')"/>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
|
||||
</xsl:if>
|
||||
|
||||
<!-- ==== primaryKey ==== -->
|
||||
<xsl:if test="@PrimaryKey = '1'">
|
||||
<xsl:attribute name="primaryKey">true</xsl:attribute>
|
||||
</xsl:if>
|
||||
|
||||
<!-- ==== required ==== -->
|
||||
<xsl:if test="@NotNull = '1'">
|
||||
<xsl:attribute name="required">true</xsl:attribute>
|
||||
</xsl:if>
|
||||
|
||||
<!-- ==== default ==== -->
|
||||
<xsl:if test="@DefaultValue != ''">
|
||||
<xsl:attribute name="default">
|
||||
<xsl:value-of select="@DefaultValue"/>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
|
||||
<!-- ==== autoIncrement ==== -->
|
||||
<xsl:if test="@AutoInc = '1'">
|
||||
<xsl:attribute name="autoIncrement">true</xsl:attribute>
|
||||
</xsl:if>
|
||||
|
||||
<!-- ==== description ==== -->
|
||||
<xsl:if test="@Comments != ''">
|
||||
<xsl:attribute name="description">
|
||||
<xsl:value-of select="@Comments"/>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
|
||||
</column>
|
||||
</xsl:template>
|
||||
|
||||
<!-- ============================================================ RELATIONS template -->
|
||||
<xsl:template match="RELATIONS_END/RELATION_END">
|
||||
|
||||
<xsl:variable name="id"><xsl:value-of select="@ID"/></xsl:variable>
|
||||
|
||||
<xsl:call-template name="show_ForeignKey">
|
||||
<xsl:with-param name="relation" select="/DBMODEL/METADATA/RELATIONS/RELATION[@ID=$id]"/>
|
||||
</xsl:call-template>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<!-- ============================================================ INDEX template -->
|
||||
<xsl:template match="INDICES/INDEX">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@IndexKind = '1' and @FKRefDef_Obj_id='-1'">
|
||||
<index>
|
||||
<xsl:attribute name="name"><xsl:value-of select="@IndexName"/></xsl:attribute>
|
||||
<xsl:apply-templates select="INDEXCOLUMNS/INDEXCOLUMN" mode="normal"/>
|
||||
</index>
|
||||
</xsl:when>
|
||||
<xsl:when test="@IndexKind = '2'">
|
||||
<unique>
|
||||
<xsl:attribute name="name"><xsl:value-of select="@IndexName"/></xsl:attribute>
|
||||
<xsl:apply-templates select="INDEXCOLUMNS/INDEXCOLUMN" mode="unique"/>
|
||||
</unique>
|
||||
</xsl:when>
|
||||
<xsl:when test="@IndexKind = '3'">
|
||||
<index>
|
||||
<xsl:attribute name="name"><xsl:value-of select="@IndexName"/></xsl:attribute>
|
||||
<xsl:apply-templates select="INDEXCOLUMNS/INDEXCOLUMN" mode="normal"/>
|
||||
<vendor type="mysql">
|
||||
<parameter name="Index_type" value="FULLTEXT"/>
|
||||
</vendor>
|
||||
</index>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!-- ============================================================ columns within an index -->
|
||||
<xsl:template match="INDICES/INDEX/INDEXCOLUMNS/INDEXCOLUMN" mode="normal">
|
||||
<xsl:variable name="columnId"><xsl:value-of select="@idColumn"/></xsl:variable>
|
||||
<index-column>
|
||||
<xsl:attribute name="name"><xsl:value-of select="//COLUMNS/COLUMN[@ID=$columnId]/@ColName"/></xsl:attribute>
|
||||
</index-column>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="INDICES/INDEX/INDEXCOLUMNS/INDEXCOLUMN" mode="unique">
|
||||
<xsl:variable name="columnId"><xsl:value-of select="@idColumn"/></xsl:variable>
|
||||
<unique-column>
|
||||
<xsl:attribute name="name"><xsl:value-of select="//COLUMNS/COLUMN[@ID=$columnId]/@ColName"/></xsl:attribute>
|
||||
</unique-column>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!-- ============================================================ show_ForeignKey -->
|
||||
<xsl:template name="show_ForeignKey">
|
||||
<xsl:param name="relation"/>
|
||||
<foreign-key>
|
||||
|
||||
<!-- foreignTable -->
|
||||
<xsl:attribute name="foreignTable">
|
||||
<xsl:value-of select="/DBMODEL/METADATA/TABLES/TABLE[@ID=$relation/@SrcTable]/@Tablename"/>
|
||||
</xsl:attribute>
|
||||
|
||||
<!-- name -->
|
||||
<xsl:attribute name="name">
|
||||
<xsl:value-of select="translate($relation/@RelationName, ' ', '_')"/>
|
||||
</xsl:attribute>
|
||||
|
||||
<!-- onDelete -->
|
||||
<xsl:attribute name="onDelete">
|
||||
|
||||
<xsl:variable name="actionId">
|
||||
<xsl:call-template name="str_replace">
|
||||
<xsl:with-param name="stringIn" select="substring-before(substring-after($relation/@RefDef,'\n'), '\n')"/>
|
||||
<xsl:with-param name="charsIn" select="'OnDelete='"/>
|
||||
<xsl:with-param name="charsOut" select="''"/>
|
||||
</xsl:call-template>
|
||||
</xsl:variable>
|
||||
|
||||
<xsl:call-template name="get_actiontype">
|
||||
<xsl:with-param name="id" select="$actionId" />
|
||||
</xsl:call-template>
|
||||
|
||||
</xsl:attribute>
|
||||
|
||||
<!-- === reference tag === -->
|
||||
<xsl:call-template name="build_fk">
|
||||
<xsl:with-param name="stringIn" select="$relation/@FKFields"/>
|
||||
</xsl:call-template>
|
||||
|
||||
</foreign-key>
|
||||
</xsl:template>
|
||||
|
||||
<!--
|
||||
============================================================
|
||||
============================================================ template "functions"
|
||||
============================================================
|
||||
-->
|
||||
|
||||
<!-- ============================================================ get_datatype -->
|
||||
<xsl:template name="get_datatype">
|
||||
<xsl:param name="id"/>
|
||||
|
||||
<xsl:variable name="type">
|
||||
<xsl:value-of select="/DBMODEL/SETTINGS/DATATYPES/DATATYPE[@ID=$id]/@TypeName"/>
|
||||
</xsl:variable>
|
||||
|
||||
<xsl:choose>
|
||||
<xsl:when test="$type = 'DATETIME'" >TIMESTAMP</xsl:when>
|
||||
<xsl:when test="$type = 'TEXT'" >LONGVARCHAR</xsl:when>
|
||||
<xsl:when test="$type = 'BOOL'" >BOOLEAN</xsl:when>
|
||||
<xsl:when test="$type = 'GEOMETRY'" >BLOB</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="$type"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!-- ============================================================ get_datasize -->
|
||||
<xsl:template name="get_datasize">
|
||||
<xsl:param name="dtpc"/>
|
||||
<xsl:param name="dtype"/>
|
||||
|
||||
<xsl:choose>
|
||||
<xsl:when test="contains('FLOAT,DOUBLE,DECIMAL',$dtype)" >
|
||||
<xsl:value-of select="substring-before($dtpc,',')"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="$dtype = 'ENUM'">
|
||||
<xsl:value-of select="''" />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="$dtpc"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!-- ============================================================ clean_dataparams -->
|
||||
<xsl:template name="clean_dataparams">
|
||||
<xsl:param name="dtp"/>
|
||||
|
||||
<xsl:variable name="dtp2">
|
||||
<xsl:call-template name="str_replace">
|
||||
<xsl:with-param name="stringIn" select="$dtp"/>
|
||||
<xsl:with-param name="charsIn" select="'('"/>
|
||||
<xsl:with-param name="charsOut" select="''"/>
|
||||
</xsl:call-template>
|
||||
</xsl:variable>
|
||||
|
||||
<xsl:call-template name="str_replace">
|
||||
<xsl:with-param name="stringIn" select="$dtp2"/>
|
||||
<xsl:with-param name="charsIn" select="')'"/>
|
||||
<xsl:with-param name="charsOut" select="''"/>
|
||||
</xsl:call-template>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!-- ============================================================ str_replace -->
|
||||
<xsl:template name="str_replace">
|
||||
<xsl:param name="stringIn"/>
|
||||
<xsl:param name="charsIn"/>
|
||||
<xsl:param name="charsOut"/>
|
||||
<xsl:choose>
|
||||
<xsl:when test="contains($stringIn,$charsIn)">
|
||||
<xsl:value-of select="concat(substring-before($stringIn,$charsIn),$charsOut)"/>
|
||||
<xsl:call-template name="str_replace">
|
||||
<xsl:with-param name="stringIn" select="substring-after($stringIn,$charsIn)"/>
|
||||
<xsl:with-param name="charsIn" select="$charsIn"/>
|
||||
<xsl:with-param name="charsOut" select="$charsOut"/>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="$stringIn"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!-- ============================================================== build_fk -->
|
||||
<xsl:template name="build_fk">
|
||||
<xsl:param name="stringIn"/>
|
||||
<xsl:variable name="FKClean">
|
||||
<xsl:value-of select="substring-before($stringIn, '\n')"/>
|
||||
</xsl:variable>
|
||||
<reference>
|
||||
<xsl:attribute name="local">
|
||||
<xsl:value-of select="substring-after($FKClean, '=')"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="foreign">
|
||||
<xsl:value-of select="substring-before($FKClean, '=')"/>
|
||||
</xsl:attribute>
|
||||
</reference>
|
||||
<xsl:if test="contains(substring-after($stringIn,'\n'),'=')">
|
||||
<xsl:call-template name="build_fk">
|
||||
<xsl:with-param name="stringIn" select="substring-after($stringIn,'\n')"/>
|
||||
</xsl:call-template>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
|
||||
<!-- ======================================================== get_actiontype -->
|
||||
|
||||
<xsl:template name="get_actiontype">
|
||||
<xsl:param name="id"/>
|
||||
|
||||
<xsl:choose>
|
||||
<xsl:when test="$id = 0">restrict</xsl:when>
|
||||
<xsl:when test="$id = 1">cascade</xsl:when>
|
||||
<xsl:when test="$id = 2">setnull</xsl:when>
|
||||
<xsl:otherwise>restrict</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
||||
26
core/vendor/propel/propel/src/Propel/Common/Pluralizer/PluralizerInterface.php
vendored
Normal file
26
core/vendor/propel/propel/src/Propel/Common/Pluralizer/PluralizerInterface.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?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\Common\Pluralizer;
|
||||
|
||||
/**
|
||||
* The generic interface to create a plural form of a name.
|
||||
*
|
||||
* @author Hans Lellelid <hans@xmpl.org>
|
||||
*/
|
||||
interface PluralizerInterface
|
||||
{
|
||||
/**
|
||||
* Generate a plural name based on the passed in root.
|
||||
* @param string $root The root that needs to be pluralized (e.g. Author)
|
||||
* @return string The plural form of $root.
|
||||
*/
|
||||
public function getPluralForm($root);
|
||||
}
|
||||
31
core/vendor/propel/propel/src/Propel/Common/Pluralizer/SimpleEnglishPluralizer.php
vendored
Normal file
31
core/vendor/propel/propel/src/Propel/Common/Pluralizer/SimpleEnglishPluralizer.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?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\Common\Pluralizer;
|
||||
|
||||
/**
|
||||
* The Propel 1.6 default English pluralizer class
|
||||
* for compatibility only.
|
||||
*
|
||||
* @author Hans Lellelid <hans@xmpl.org>
|
||||
*/
|
||||
class SimpleEnglishPluralizer implements PluralizerInterface
|
||||
{
|
||||
/**
|
||||
* Generate a plural name based on the passed in root.
|
||||
*
|
||||
* @param string $root The root that needs to be pluralized (e.g. Author)
|
||||
* @return string The plural form of $root (e.g. Authors).
|
||||
*/
|
||||
public function getPluralForm($root)
|
||||
{
|
||||
return $root . 's';
|
||||
}
|
||||
}
|
||||
151
core/vendor/propel/propel/src/Propel/Common/Pluralizer/StandardEnglishPluralizer.php
vendored
Normal file
151
core/vendor/propel/propel/src/Propel/Common/Pluralizer/StandardEnglishPluralizer.php
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
<?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\Common\Pluralizer;
|
||||
|
||||
/**
|
||||
* Standard replacement English pluralizer class. Based on the links below
|
||||
*
|
||||
* @link http://kuwamoto.org/2007/12/17/improved-pluralizing-in-php-actionscript-and-ror/
|
||||
* @link http://blogs.msdn.com/dmitryr/archive/2007/01/11/simple-english-noun-pluralizer-in-c.aspx
|
||||
* @link http://api.cakephp.org/view_source/inflector/
|
||||
*
|
||||
* @author paul.hanssen
|
||||
*/
|
||||
class StandardEnglishPluralizer implements PluralizerInterface
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $plural = array(
|
||||
'(matr|vert|ind)(ix|ex)' => '\1ices',
|
||||
'(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|vir)us' => '\1i',
|
||||
'(buffal|tomat)o' => '\1oes',
|
||||
|
||||
'x' => 'xes',
|
||||
'ch' => 'ches',
|
||||
'sh' => 'shes',
|
||||
'ss' => 'sses',
|
||||
|
||||
'ay' => 'ays',
|
||||
'ey' => 'eys',
|
||||
'iy' => 'iys',
|
||||
'oy' => 'oys',
|
||||
'uy' => 'uys',
|
||||
'y' => 'ies',
|
||||
|
||||
'ao' => 'aos',
|
||||
'eo' => 'eos',
|
||||
'io' => 'ios',
|
||||
'oo' => 'oos',
|
||||
'uo' => 'uos',
|
||||
'o' => 'os',
|
||||
|
||||
'us' => 'uses',
|
||||
|
||||
'cis' => 'ces',
|
||||
'sis' => 'ses',
|
||||
'xis' => 'xes',
|
||||
|
||||
'zoon' => 'zoa',
|
||||
|
||||
'itis' => 'itis',
|
||||
'ois' => 'ois',
|
||||
'pox' => 'pox',
|
||||
'ox' => 'oxes',
|
||||
|
||||
'foot' => 'feet',
|
||||
'goose' => 'geese',
|
||||
'tooth' => 'teeth',
|
||||
'quiz' => 'quizzes',
|
||||
'alias' => 'aliases',
|
||||
|
||||
'alf' => 'alves',
|
||||
'elf' => 'elves',
|
||||
'olf' => 'olves',
|
||||
'arf' => 'arves',
|
||||
'nife' => 'nives',
|
||||
'life' => 'lives'
|
||||
);
|
||||
|
||||
protected $irregular = array(
|
||||
'leaf' => 'leaves',
|
||||
'loaf' => 'loaves',
|
||||
'move' => 'moves',
|
||||
'foot' => 'feet',
|
||||
'goose' => 'geese',
|
||||
'genus' => 'genera',
|
||||
'sex' => 'sexes',
|
||||
'ox' => 'oxen',
|
||||
'child' => 'children',
|
||||
'man' => 'men',
|
||||
'tooth' => 'teeth',
|
||||
'person' => 'people',
|
||||
'wife' => 'wives',
|
||||
'mythos' => 'mythoi',
|
||||
'testis' => 'testes',
|
||||
'numen' => 'numina',
|
||||
'quiz' => 'quizzes',
|
||||
'alias' => 'aliases',
|
||||
);
|
||||
|
||||
protected $uncountable = array(
|
||||
'sheep',
|
||||
'fish',
|
||||
'deer',
|
||||
'series',
|
||||
'species',
|
||||
'money',
|
||||
'rice',
|
||||
'information',
|
||||
'equipment',
|
||||
'news',
|
||||
'people',
|
||||
);
|
||||
|
||||
/**
|
||||
* Generate a plural name based on the passed in root.
|
||||
* @param string $root The root that needs to be pluralized (e.g. Author)
|
||||
* @return string The plural form of $root (e.g. Authors).
|
||||
*/
|
||||
public function getPluralForm($root)
|
||||
{
|
||||
// save some time in the case that singular and plural are the same
|
||||
if (in_array(strtolower($root), $this->uncountable)) {
|
||||
return $root;
|
||||
}
|
||||
|
||||
// check for irregular singular words
|
||||
foreach ($this->irregular as $pattern => $result) {
|
||||
$searchPattern = '/' . $pattern . '$/i';
|
||||
if (preg_match($searchPattern, $root)) {
|
||||
$replacement = preg_replace($searchPattern, $result, $root);
|
||||
// look at the first char and see if it's upper case
|
||||
// I know it won't handle more than one upper case char here (but I'm OK with that)
|
||||
if (preg_match('/^[A-Z]/', $root)) {
|
||||
$replacement = ucfirst($replacement);
|
||||
}
|
||||
|
||||
return $replacement;
|
||||
}
|
||||
}
|
||||
|
||||
// check for irregular singular suffixes
|
||||
foreach ($this->plural as $pattern => $result) {
|
||||
$searchPattern = '/' . $pattern . '$/i';
|
||||
if (preg_match($searchPattern, $root)) {
|
||||
return preg_replace($searchPattern, $result, $root);
|
||||
}
|
||||
}
|
||||
|
||||
// fallback to naive pluralization
|
||||
return $root . 's';
|
||||
}
|
||||
}
|
||||
138
core/vendor/propel/propel/src/Propel/Generator/Behavior/AggregateColumn/AggregateColumnBehavior.php
vendored
Normal file
138
core/vendor/propel/propel/src/Propel/Generator/Behavior/AggregateColumn/AggregateColumnBehavior.php
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
<?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\Behavior\AggregateColumn;
|
||||
|
||||
use Propel\Generator\Model\Behavior;
|
||||
|
||||
/**
|
||||
* Keeps an aggregate column updated with related table
|
||||
*
|
||||
* @author François Zaninotto
|
||||
*/
|
||||
class AggregateColumnBehavior extends Behavior
|
||||
{
|
||||
// default parameters value
|
||||
protected $parameters = array(
|
||||
'name' => null,
|
||||
'expression' => null,
|
||||
'condition' => null,
|
||||
'foreign_table' => null,
|
||||
'foreign_schema' => null,
|
||||
);
|
||||
|
||||
/**
|
||||
* Add the aggregate key to the current table
|
||||
*/
|
||||
public function modifyTable()
|
||||
{
|
||||
$table = $this->getTable();
|
||||
if (!$columnName = $this->getParameter('name')) {
|
||||
throw new \InvalidArgumentException(sprintf('You must define a \'name\' parameter for the \'aggregate_column\' behavior in the \'%s\' table', $table->getName()));
|
||||
}
|
||||
|
||||
// add the aggregate column if not present
|
||||
if (!$table->hasColumn($columnName)) {
|
||||
$table->addColumn(array(
|
||||
'name' => $columnName,
|
||||
'type' => 'INTEGER',
|
||||
));
|
||||
}
|
||||
|
||||
// add a behavior in the foreign table to autoupdate the aggregate column
|
||||
$foreignTable = $this->getForeignTable();
|
||||
if (!$foreignTable->hasBehavior('concrete_inheritance_parent')) {
|
||||
$relationBehavior = new AggregateColumnRelationBehavior();
|
||||
$relationBehavior->setName('aggregate_column_relation');
|
||||
$relationBehavior->addParameter(array('name' => 'foreign_table', 'value' => $table->getName()));
|
||||
$relationBehavior->addParameter(array('name' => 'update_method', 'value' => 'update' . $this->getColumn()->getPhpName()));
|
||||
$foreignTable->addBehavior($relationBehavior);
|
||||
}
|
||||
}
|
||||
|
||||
public function objectMethods($builder)
|
||||
{
|
||||
if (!$this->getParameter('foreign_table')) {
|
||||
throw new \InvalidArgumentException(sprintf('You must define a \'foreign_table\' parameter for the \'aggregate_column\' behavior in the \'%s\' table', $this->getTable()->getName()));
|
||||
}
|
||||
$script = '';
|
||||
$script .= $this->addObjectCompute();
|
||||
$script .= $this->addObjectUpdate();
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
protected function addObjectCompute()
|
||||
{
|
||||
$conditions = array();
|
||||
if ($this->getParameter('condition')) {
|
||||
$conditions[] = $this->getParameter('condition');
|
||||
}
|
||||
|
||||
$bindings = array();
|
||||
$database = $this->getTable()->getDatabase();
|
||||
foreach ($this->getForeignKey()->getColumnObjectsMapping() as $index => $columnReference) {
|
||||
$conditions[] = $columnReference['local']->getFullyQualifiedName() . ' = :p' . ($index + 1);
|
||||
$bindings[$index + 1] = $columnReference['foreign']->getPhpName();
|
||||
}
|
||||
$tableName = $database->getTablePrefix() . $this->getParameter('foreign_table');
|
||||
if ($database->getPlatform()->supportsSchemas() && $this->getParameter('foreign_schema')) {
|
||||
$tableName = $this->getParameter('foreign_schema')
|
||||
.$database->getPlatform()->getSchemaDelimiter()
|
||||
.$tableName;
|
||||
}
|
||||
$sql = sprintf('SELECT %s FROM %s WHERE %s',
|
||||
$this->getParameter('expression'),
|
||||
$database->getPlatform()->quoteIdentifier($tableName),
|
||||
implode(' AND ', $conditions)
|
||||
);
|
||||
|
||||
return $this->renderTemplate('objectCompute', array(
|
||||
'column' => $this->getColumn(),
|
||||
'sql' => $sql,
|
||||
'bindings' => $bindings,
|
||||
));
|
||||
}
|
||||
|
||||
protected function addObjectUpdate()
|
||||
{
|
||||
return $this->renderTemplate('objectUpdate', array(
|
||||
'column' => $this->getColumn(),
|
||||
));
|
||||
}
|
||||
|
||||
protected function getForeignTable()
|
||||
{
|
||||
$database = $this->getTable()->getDatabase();
|
||||
$tableName = $database->getTablePrefix() . $this->getParameter('foreign_table');
|
||||
if ($database->getPlatform()->supportsSchemas() && $this->getParameter('foreign_schema')) {
|
||||
$tableName = $this->getParameter('foreign_schema'). $database->getPlatform()->getSchemaDelimiter() . $tableName;
|
||||
}
|
||||
|
||||
return $database->getTable($tableName);
|
||||
}
|
||||
|
||||
protected function getForeignKey()
|
||||
{
|
||||
$foreignTable = $this->getForeignTable();
|
||||
// let's infer the relation from the foreign table
|
||||
$fks = $foreignTable->getForeignKeysReferencingTable($this->getTable()->getName());
|
||||
if (!$fks) {
|
||||
throw new \InvalidArgumentException(sprintf('You must define a foreign key to the \'%s\' table in the \'%s\' table to enable the \'aggregate_column\' behavior', $this->getTable()->getName(), $foreignTable->getName()));
|
||||
}
|
||||
// FIXME doesn't work when more than one fk to the same table
|
||||
return array_shift($fks);
|
||||
}
|
||||
|
||||
protected function getColumn()
|
||||
{
|
||||
return $this->getTable()->getColumn($this->getParameter('name'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
<?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\Behavior\AggregateColumn;
|
||||
|
||||
use Propel\Generator\Model\Behavior;
|
||||
|
||||
/**
|
||||
* Keeps an aggregate column updated with related table
|
||||
*
|
||||
* @author François Zaninotto
|
||||
*/
|
||||
class AggregateColumnRelationBehavior extends Behavior
|
||||
{
|
||||
// default parameters value
|
||||
protected $parameters = array(
|
||||
'foreign_table' => '',
|
||||
'update_method' => '',
|
||||
);
|
||||
|
||||
public function postSave($builder)
|
||||
{
|
||||
$relationName = $this->getRelationName($builder);
|
||||
|
||||
return "\$this->updateRelated{$relationName}(\$con);";
|
||||
}
|
||||
|
||||
// no need for a postDelete() hook, since delete() uses Query::delete(),
|
||||
// which already has a hook
|
||||
|
||||
public function objectAttributes($builder)
|
||||
{
|
||||
$relationName = $this->getRelationName($builder);
|
||||
|
||||
return "protected \$old{$relationName};
|
||||
";
|
||||
}
|
||||
|
||||
public function objectMethods($builder)
|
||||
{
|
||||
return $this->addObjectUpdateRelated($builder);
|
||||
}
|
||||
|
||||
protected function addObjectUpdateRelated($builder)
|
||||
{
|
||||
$relationName = $this->getRelationName($builder);
|
||||
|
||||
return $this->renderTemplate('objectUpdateRelated', array(
|
||||
'relationName' => $relationName,
|
||||
'variableName' => lcfirst($relationName),
|
||||
'updateMethodName' => $this->getParameter('update_method'),
|
||||
));
|
||||
}
|
||||
|
||||
public function objectFilter(&$script, $builder)
|
||||
{
|
||||
$relationName = $this->getRelationName($builder);
|
||||
$relatedClass = $builder->getClassNameFromBuilder($builder->getNewStubObjectBuilder($this->getForeignTable()));
|
||||
$search = " public function set{$relationName}({$relatedClass} \$v = null)
|
||||
{";
|
||||
$replace = $search . "
|
||||
// aggregate_column_relation behavior
|
||||
if (null !== \$this->a{$relationName} && \$v !== \$this->a{$relationName}) {
|
||||
\$this->old{$relationName} = \$this->a{$relationName};
|
||||
}";
|
||||
$script = str_replace($search, $replace, $script);
|
||||
}
|
||||
|
||||
public function preUpdateQuery($builder)
|
||||
{
|
||||
return $this->getFindRelated($builder);
|
||||
}
|
||||
|
||||
public function preDeleteQuery($builder)
|
||||
{
|
||||
return $this->getFindRelated($builder);
|
||||
}
|
||||
|
||||
protected function getFindRelated($builder)
|
||||
{
|
||||
$relationName = $this->getRelationName($builder);
|
||||
|
||||
return "\$this->findRelated{$relationName}s(\$con);";
|
||||
}
|
||||
|
||||
public function postUpdateQuery($builder)
|
||||
{
|
||||
return $this->getUpdateRelated($builder);
|
||||
}
|
||||
|
||||
public function postDeleteQuery($builder)
|
||||
{
|
||||
return $this->getUpdateRelated($builder);
|
||||
}
|
||||
|
||||
protected function getUpdateRelated($builder)
|
||||
{
|
||||
$relationName = $this->getRelationName($builder);
|
||||
|
||||
return "\$this->updateRelated{$relationName}s(\$con);";
|
||||
}
|
||||
|
||||
public function queryMethods($builder)
|
||||
{
|
||||
$script = '';
|
||||
$script .= $this->addQueryFindRelated($builder);
|
||||
$script .= $this->addQueryUpdateRelated($builder);
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
protected function addQueryFindRelated($builder)
|
||||
{
|
||||
$foreignKey = $this->getForeignKey();
|
||||
$foreignQueryBuilder = $builder->getNewStubQueryBuilder($foreignKey->getForeignTable());
|
||||
$relationName = $this->getRelationName($builder);
|
||||
|
||||
$builder->declareClassNamespace(
|
||||
$foreignKey->getForeignTable()->getPhpName() . 'Query',
|
||||
$foreignKey->getForeignTable()->getNamespace()
|
||||
);
|
||||
|
||||
return $this->renderTemplate('queryFindRelated', array(
|
||||
'foreignTable' => $this->getForeignTable(),
|
||||
'relationName' => $relationName,
|
||||
'variableName' => lcfirst($relationName),
|
||||
'foreignQueryName' => $foreignQueryBuilder->getClassName(),
|
||||
'refRelationName' => $builder->getRefFKPhpNameAffix($foreignKey),
|
||||
));
|
||||
}
|
||||
|
||||
protected function addQueryUpdateRelated($builder)
|
||||
{
|
||||
$relationName = $this->getRelationName($builder);
|
||||
|
||||
return $this->renderTemplate('queryUpdateRelated', array(
|
||||
'relationName' => $relationName,
|
||||
'variableName' => lcfirst($relationName),
|
||||
'updateMethodName' => $this->getParameter('update_method'),
|
||||
));
|
||||
}
|
||||
|
||||
protected function getForeignTable()
|
||||
{
|
||||
return $this->getTable()->getDatabase()->getTable($this->getParameter('foreign_table'));
|
||||
}
|
||||
|
||||
protected function getForeignKey()
|
||||
{
|
||||
$foreignTable = $this->getForeignTable();
|
||||
// let's infer the relation from the foreign table
|
||||
$fks = $this->getTable()->getForeignKeysReferencingTable($foreignTable->getName());
|
||||
// FIXME doesn't work when more than one fk to the same table
|
||||
return array_shift($fks);
|
||||
}
|
||||
|
||||
protected function getRelationName($builder)
|
||||
{
|
||||
return $builder->getFKPhpNameAffix($this->getForeignKey());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
|
||||
/**
|
||||
* Computes the value of the aggregate column <?=$column->getName()?>
|
||||
*
|
||||
* @param ConnectionInterface $con A connection object
|
||||
*
|
||||
* @return mixed The scalar result from the aggregate query
|
||||
*/
|
||||
public function compute<?=$column->getPhpName()?>(ConnectionInterface $con)
|
||||
{
|
||||
$stmt = $con->prepare('<?=$sql?>');
|
||||
<?php foreach ($bindings as $key => $binding):?>
|
||||
$stmt->bindValue(':p<?=$key?>', $this->get<?=$binding?>());
|
||||
<?php endforeach;?>
|
||||
$stmt->execute();
|
||||
|
||||
return $stmt->fetchColumn();
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
/**
|
||||
* Updates the aggregate column <?=$column->getName()?>
|
||||
*
|
||||
* @param ConnectionInterface $con A connection object
|
||||
*/
|
||||
public function update<?=$column->getPhpName()?>(ConnectionInterface $con)
|
||||
{
|
||||
$this->set<?=$column->getPhpName()?>($this->compute<?=$column->getPhpName()?>($con));
|
||||
$this->save($con);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
/**
|
||||
* Update the aggregate column in the related <?=$relationName?> object
|
||||
*
|
||||
* @param ConnectionInterface $con A connection object
|
||||
*/
|
||||
protected function updateRelated<?=$relationName?>(ConnectionInterface $con)
|
||||
{
|
||||
if ($<?=$variableName?> = $this->get<?=$relationName?>()) {
|
||||
$<?=$variableName?>-><?=$updateMethodName?>($con);
|
||||
}
|
||||
if ($this->old<?=$relationName?>) {
|
||||
$this->old<?=$relationName?>-><?=$updateMethodName?>($con);
|
||||
$this->old<?=$relationName?> = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
/**
|
||||
* Finds the related <?=$foreignTable->getPhpName()?> objects and keep them for later
|
||||
*
|
||||
* @param ConnectionInterface $con A connection object
|
||||
*/
|
||||
protected function findRelated<?=$relationName?>s($con)
|
||||
{
|
||||
$criteria = clone $this;
|
||||
if ($this->useAliasInSQL) {
|
||||
$alias = $this->getModelAlias();
|
||||
$criteria->removeAlias($alias);
|
||||
} else {
|
||||
$alias = '';
|
||||
}
|
||||
$this-><?=$variableName?>s = <?=$foreignQueryName?>::create()
|
||||
->join<?=$refRelationName?>($alias)
|
||||
->mergeWith($criteria)
|
||||
->find($con);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
protected function updateRelated<?=$relationName?>s($con)
|
||||
{
|
||||
foreach ($this-><?=$variableName?>s as $<?=$variableName?>) {
|
||||
$<?=$variableName?>-><?= $updateMethodName ?>($con);
|
||||
}
|
||||
$this-><?=$variableName?>s = array();
|
||||
}
|
||||
202
core/vendor/propel/propel/src/Propel/Generator/Behavior/Archivable/ArchivableBehavior.php
vendored
Normal file
202
core/vendor/propel/propel/src/Propel/Generator/Behavior/Archivable/ArchivableBehavior.php
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
<?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\Behavior\Archivable;
|
||||
|
||||
use Propel\Generator\Exception\InvalidArgumentException;
|
||||
use Propel\Generator\Model\Behavior;
|
||||
use Propel\Generator\Model\Index;
|
||||
|
||||
/**
|
||||
* Keeps tracks of an ActiveRecord object, even after deletion
|
||||
*
|
||||
* @author Francois Zaninotto
|
||||
*/
|
||||
class ArchivableBehavior extends Behavior
|
||||
{
|
||||
// default parameters value
|
||||
protected $parameters = array(
|
||||
'archive_table' => '',
|
||||
'archive_phpname' => null,
|
||||
'archive_class' => '',
|
||||
'log_archived_at' => 'true',
|
||||
'archived_at_column' => 'archived_at',
|
||||
'archive_on_insert' => 'false',
|
||||
'archive_on_update' => 'false',
|
||||
'archive_on_delete' => 'true',
|
||||
);
|
||||
|
||||
protected $archiveTable;
|
||||
protected $objectBuilderModifier;
|
||||
protected $queryBuilderModifier;
|
||||
|
||||
public function modifyDatabase()
|
||||
{
|
||||
foreach ($this->getDatabase()->getTables() as $table) {
|
||||
if ($table->hasBehavior($this->getName())) {
|
||||
// don't add the same behavior twice
|
||||
continue;
|
||||
}
|
||||
if (property_exists($table, 'isArchiveTable')) {
|
||||
// don't add the behavior to archive tables
|
||||
continue;
|
||||
}
|
||||
$b = clone $this;
|
||||
$table->addBehavior($b);
|
||||
}
|
||||
}
|
||||
|
||||
public function modifyTable()
|
||||
{
|
||||
if ($this->getParameter('archive_class') && $this->getParameter('archive_table')) {
|
||||
throw new InvalidArgumentException('Please set only one of the two parameters "archive_class" and "archive_table".');
|
||||
}
|
||||
if (!$this->getParameter('archive_class')) {
|
||||
$this->addArchiveTable();
|
||||
}
|
||||
}
|
||||
|
||||
protected function addArchiveTable()
|
||||
{
|
||||
$table = $this->getTable();
|
||||
$database = $table->getDatabase();
|
||||
$archiveTableName = $this->getParameter('archive_table') ? $this->getParameter('archive_table') : ($this->getTable()->getName() . '_archive');
|
||||
if (!$database->hasTable($archiveTableName)) {
|
||||
// create the version table
|
||||
$archiveTable = $database->addTable(array(
|
||||
'name' => $archiveTableName,
|
||||
'phpName' => $this->getParameter('archive_phpname'),
|
||||
'package' => $table->getPackage(),
|
||||
'schema' => $table->getSchema(),
|
||||
'namespace' => $table->getNamespace() ? '\\' . $table->getNamespace() : null,
|
||||
));
|
||||
$archiveTable->isArchiveTable = true;
|
||||
// copy all the columns
|
||||
foreach ($table->getColumns() as $column) {
|
||||
$columnInArchiveTable = clone $column;
|
||||
if ($columnInArchiveTable->hasReferrers()) {
|
||||
$columnInArchiveTable->clearReferrers();
|
||||
}
|
||||
if ($columnInArchiveTable->isAutoincrement()) {
|
||||
$columnInArchiveTable->setAutoIncrement(false);
|
||||
}
|
||||
$archiveTable->addColumn($columnInArchiveTable);
|
||||
}
|
||||
// add archived_at column
|
||||
if ($this->getParameter('log_archived_at') == 'true') {
|
||||
$archiveTable->addColumn(array(
|
||||
'name' => $this->getParameter('archived_at_column'),
|
||||
'type' => 'TIMESTAMP'
|
||||
));
|
||||
}
|
||||
// do not copy foreign keys
|
||||
// copy the indices
|
||||
foreach ($table->getIndices() as $index) {
|
||||
$copiedIndex = clone $index;
|
||||
$copiedIndex->setName('');
|
||||
$archiveTable->addIndex($copiedIndex);
|
||||
}
|
||||
// copy unique indices to indices
|
||||
// see https://github.com/propelorm/Propel/issues/175 for details
|
||||
foreach ($table->getUnices() as $unique) {
|
||||
$index = new Index();
|
||||
foreach ($unique->getColumns() as $columnName) {
|
||||
if ($size = $unique->getColumnSize($columnName)) {
|
||||
$index->addColumn(array('name' => $columnName, 'size' => $size));
|
||||
} else {
|
||||
$index->addColumn(array('name' => $columnName));
|
||||
}
|
||||
}
|
||||
$archiveTable->addIndex($index);
|
||||
}
|
||||
// every behavior adding a table should re-execute database behaviors
|
||||
foreach ($database->getBehaviors() as $behavior) {
|
||||
$behavior->modifyDatabase();
|
||||
}
|
||||
$this->archiveTable = $archiveTable;
|
||||
} else {
|
||||
$this->archiveTable = $database->getTable($archiveTableName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Table
|
||||
*/
|
||||
public function getArchiveTable()
|
||||
{
|
||||
return $this->archiveTable;
|
||||
}
|
||||
|
||||
public function getArchiveTablePhpName($builder)
|
||||
{
|
||||
if ($this->hasArchiveClass()) {
|
||||
return $this->getParameter('archive_class');
|
||||
}
|
||||
|
||||
return $builder->getClassNameFromBuilder($builder->getNewStubObjectBuilder($this->getArchiveTable()));
|
||||
}
|
||||
|
||||
public function getArchiveTableQueryName($builder)
|
||||
{
|
||||
if ($this->hasArchiveClass()) {
|
||||
return $this->getParameter('archive_class') . 'Query';
|
||||
}
|
||||
|
||||
return $builder->getClassNameFromBuilder($builder->getNewStubQueryBuilder($this->getArchiveTable()));
|
||||
}
|
||||
|
||||
public function hasArchiveClass()
|
||||
{
|
||||
return $this->getParameter('archive_class') ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Column
|
||||
*/
|
||||
public function getArchivedAtColumn()
|
||||
{
|
||||
if ($this->getArchiveTable() && 'true' === $this->getParameter('log_archived_at')) {
|
||||
return $this->getArchiveTable()->getColumn($this->getParameter('archived_at_column'));
|
||||
}
|
||||
}
|
||||
|
||||
public function isArchiveOnInsert()
|
||||
{
|
||||
return 'true' === $this->getParameter('archive_on_insert');
|
||||
}
|
||||
|
||||
public function isArchiveOnUpdate()
|
||||
{
|
||||
return 'true' === $this->getParameter('archive_on_update');
|
||||
}
|
||||
|
||||
public function isArchiveOnDelete()
|
||||
{
|
||||
return 'true' === $this->getParameter('archive_on_delete');
|
||||
}
|
||||
|
||||
public function getObjectBuilderModifier()
|
||||
{
|
||||
if (null === $this->objectBuilderModifier) {
|
||||
$this->objectBuilderModifier = new ArchivableBehaviorObjectBuilderModifier($this);
|
||||
}
|
||||
|
||||
return $this->objectBuilderModifier;
|
||||
}
|
||||
|
||||
public function getQueryBuilderModifier()
|
||||
{
|
||||
if (null === $this->queryBuilderModifier) {
|
||||
$this->queryBuilderModifier = new ArchivableBehaviorQueryBuilderModifier($this);
|
||||
}
|
||||
|
||||
return $this->queryBuilderModifier;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
<?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\Behavior\Archivable;
|
||||
|
||||
/**
|
||||
* Keeps tracks of an ActiveRecord object, even after deletion
|
||||
*
|
||||
* @author François Zaninotto
|
||||
*/
|
||||
class ArchivableBehaviorObjectBuilderModifier
|
||||
{
|
||||
protected $behavior;
|
||||
protected $table;
|
||||
protected $builder;
|
||||
|
||||
public function __construct($behavior)
|
||||
{
|
||||
$this->behavior = $behavior;
|
||||
$this->table = $behavior->getTable();
|
||||
}
|
||||
|
||||
protected function getParameter($key)
|
||||
{
|
||||
return $this->behavior->getParameter($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the PHP code to be added to the builder
|
||||
*/
|
||||
public function objectAttributes($builder)
|
||||
{
|
||||
$script = '';
|
||||
if ($this->behavior->isArchiveOnInsert()) {
|
||||
$script .= "protected \$archiveOnInsert = true;
|
||||
";
|
||||
}
|
||||
if ($this->behavior->isArchiveOnUpdate()) {
|
||||
$script .= "protected \$archiveOnUpdate = true;
|
||||
";
|
||||
}
|
||||
if ($this->behavior->isArchiveOnDelete()) {
|
||||
$script .= "protected \$archiveOnDelete = true;
|
||||
";
|
||||
}
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the PHP code to be added to the builder
|
||||
*/
|
||||
public function postInsert($builder)
|
||||
{
|
||||
if ($this->behavior->isArchiveOnInsert()) {
|
||||
return "if (\$this->archiveOnInsert) {
|
||||
\$this->archive(\$con);
|
||||
} else {
|
||||
\$this->archiveOnInsert = true;
|
||||
}";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the PHP code to be added to the builder
|
||||
*/
|
||||
public function postUpdate($builder)
|
||||
{
|
||||
if ($this->behavior->isArchiveOnUpdate()) {
|
||||
return "if (\$this->archiveOnUpdate) {
|
||||
\$this->archive(\$con);
|
||||
} else {
|
||||
\$this->archiveOnUpdate = true;
|
||||
}";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Using preDelete rather than postDelete to allow user to retrieve
|
||||
* related records and archive them before cascade deletion.
|
||||
*
|
||||
* The actual deletion is made by the query object, so the AR class must tell
|
||||
* the query class to enable or disable archiveOnDelete.
|
||||
*
|
||||
* @return string the PHP code to be added to the builder
|
||||
*/
|
||||
public function preDelete($builder)
|
||||
{
|
||||
if ($this->behavior->isArchiveOnDelete()) {
|
||||
return $this->behavior->renderTemplate('objectPreDelete', array(
|
||||
'queryClassName' => $builder->getQueryClassName(),
|
||||
'isAddHooks' => $builder->getGeneratorConfig()->getBuildProperty('addHooks'),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the PHP code to be added to the builder
|
||||
*/
|
||||
public function objectMethods($builder)
|
||||
{
|
||||
$this->builder = $builder;
|
||||
$script = '';
|
||||
$script .= $this->addGetArchive($builder);
|
||||
$script .= $this->addArchive($builder);
|
||||
$script .= $this->addRestoreFromArchive($builder);
|
||||
$script .= $this->addPopulateFromArchive($builder);
|
||||
if ($this->behavior->isArchiveOnInsert() || $this->behavior->isArchiveOnUpdate()) {
|
||||
$script .= $this->addSaveWithoutArchive($builder);
|
||||
}
|
||||
if ($this->behavior->isArchiveOnDelete()) {
|
||||
$script .= $this->addDeleteWithoutArchive($builder);
|
||||
}
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the PHP code to be added to the builder
|
||||
*/
|
||||
public function addGetArchive($builder)
|
||||
{
|
||||
return $this->behavior->renderTemplate('objectGetArchive', array(
|
||||
'archiveTablePhpName' => $this->behavior->getArchiveTablePhpName($builder),
|
||||
'archiveTableQueryName' => $this->behavior->getArchiveTableQueryName($builder),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the PHP code to be added to the builder
|
||||
*/
|
||||
public function addArchive($builder)
|
||||
{
|
||||
return $this->behavior->renderTemplate('objectArchive', array(
|
||||
'archiveTablePhpName' => $this->behavior->getArchiveTablePhpName($builder),
|
||||
'archiveTableQueryName' => $this->behavior->getArchiveTableQueryName($builder),
|
||||
'archivedAtColumn' => $this->behavior->getArchivedAtColumn(),
|
||||
'hasArchiveClass' => $this->behavior->hasArchiveClass()
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string the PHP code to be added to the builder
|
||||
*/
|
||||
public function addRestoreFromArchive($builder)
|
||||
{
|
||||
return $this->behavior->renderTemplate('objectRestoreFromArchive', array(
|
||||
'objectClassName' => $this->builder->getObjectClassName(),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a method to populate the current AR object based on an archive object.
|
||||
* This method is necessary because the archive's copyInto() may include the archived_at column
|
||||
* and therefore cannot be used. Besides, the way autoincremented PKs are handled should be explicit.
|
||||
*
|
||||
* @return string the PHP code to be added to the builder
|
||||
*/
|
||||
public function addPopulateFromArchive($builder)
|
||||
{
|
||||
return $this->behavior->renderTemplate('objectPopulateFromArchive', array(
|
||||
'archiveTablePhpName' => $this->behavior->getArchiveTablePhpName($builder),
|
||||
'usesAutoIncrement' => $this->table->hasAutoIncrementPrimaryKey(),
|
||||
'objectClassName' => $this->builder->getObjectClassName(),
|
||||
'columns' => $this->table->getColumns(),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the PHP code to be added to the builder
|
||||
*/
|
||||
public function addSaveWithoutArchive($builder)
|
||||
{
|
||||
return $this->behavior->renderTemplate('objectSaveWithoutArchive', array(
|
||||
'objectClassName' => $this->builder->getObjectClassName(),
|
||||
'isArchiveOnInsert' => $this->behavior->isArchiveOnInsert(),
|
||||
'isArchiveOnUpdate' => $this->behavior->isArchiveOnUpdate(),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the PHP code to be added to the builder
|
||||
*/
|
||||
public function addDeleteWithoutArchive($builder)
|
||||
{
|
||||
return $this->behavior->renderTemplate('objectDeleteWithoutArchive', array(
|
||||
'objectClassName' => $this->builder->getObjectClassName(),
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
<?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\Behavior\Archivable;
|
||||
|
||||
/**
|
||||
* Keeps tracks of an ActiveRecord object, even after deletion
|
||||
*
|
||||
* @author François Zaninotto
|
||||
*/
|
||||
class ArchivableBehaviorQueryBuilderModifier
|
||||
{
|
||||
protected $behavior;
|
||||
protected $table;
|
||||
|
||||
public function __construct($behavior)
|
||||
{
|
||||
$this->behavior = $behavior;
|
||||
$this->table = $behavior->getTable();
|
||||
}
|
||||
|
||||
protected function getParameter($key)
|
||||
{
|
||||
return $this->behavior->getParameter($key);
|
||||
}
|
||||
|
||||
public function queryAttributes($builder)
|
||||
{
|
||||
$script = '';
|
||||
if ($this->behavior->isArchiveOnUpdate()) {
|
||||
$script .= "protected \$archiveOnUpdate = true;
|
||||
";
|
||||
}
|
||||
if ($this->behavior->isArchiveOnDelete()) {
|
||||
$script .= "protected \$archiveOnDelete = true;
|
||||
";
|
||||
}
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
public function preDeleteQuery($builder)
|
||||
{
|
||||
if ($this->behavior->isArchiveOnDelete()) {
|
||||
return "
|
||||
if (\$this->archiveOnDelete) {
|
||||
\$this->archive(\$con);
|
||||
} else {
|
||||
\$this->archiveOnDelete = true;
|
||||
}
|
||||
";
|
||||
}
|
||||
}
|
||||
|
||||
public function postUpdateQuery($builder)
|
||||
{
|
||||
if ($this->behavior->isArchiveOnUpdate()) {
|
||||
return "
|
||||
if (\$this->archiveOnUpdate) {
|
||||
\$this->archive(\$con);
|
||||
} else {
|
||||
\$this->archiveOnUpdate = true;
|
||||
}
|
||||
";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the PHP code to be added to the builder
|
||||
*/
|
||||
public function queryMethods($builder)
|
||||
{
|
||||
$script = '';
|
||||
$script .= $this->addArchive($builder);
|
||||
if ($this->behavior->isArchiveOnUpdate()) {
|
||||
$script .= $this->addSetArchiveOnUpdate($builder);
|
||||
$script .= $this->addUpdateWithoutArchive($builder);
|
||||
}
|
||||
if ($this->behavior->isArchiveOnDelete()) {
|
||||
$script .= $this->addSetArchiveOnDelete($builder);
|
||||
$script .= $this->addDeleteWithoutArchive($builder);
|
||||
}
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the PHP code to be added to the builder
|
||||
*/
|
||||
protected function addArchive($builder)
|
||||
{
|
||||
return $this->behavior->renderTemplate('queryArchive', array(
|
||||
'archiveTablePhpName' => $this->behavior->getArchiveTablePhpName($builder),
|
||||
'modelTableMap' => $builder->getTableMapClass(),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the PHP code to be added to the builder
|
||||
*/
|
||||
public function addSetArchiveOnUpdate($builder)
|
||||
{
|
||||
return $this->behavior->renderTemplate('querySetArchiveOnUpdate');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the PHP code to be added to the builder
|
||||
*/
|
||||
public function addUpdateWithoutArchive($builder)
|
||||
{
|
||||
return $this->behavior->renderTemplate('queryUpdateWithoutArchive');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the PHP code to be added to the builder
|
||||
*/
|
||||
public function addSetArchiveOnDelete($builder)
|
||||
{
|
||||
return $this->behavior->renderTemplate('querySetArchiveOnDelete');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the PHP code to be added to the builder
|
||||
*/
|
||||
public function addDeleteWithoutArchive($builder)
|
||||
{
|
||||
return $this->behavior->renderTemplate('queryDeleteWithoutArchive');
|
||||
}
|
||||
}
|
||||
29
core/vendor/propel/propel/src/Propel/Generator/Behavior/Archivable/templates/objectArchive.php
vendored
Normal file
29
core/vendor/propel/propel/src/Propel/Generator/Behavior/Archivable/templates/objectArchive.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copy the data of the current object into a $archiveTablePhpName archive object.
|
||||
* The archived object is then saved.
|
||||
* If the current object has already been archived, the archived object
|
||||
* is updated and not duplicated.
|
||||
*
|
||||
* @param ConnectionInterface $con Optional connection object
|
||||
*
|
||||
* @throws PropelException If the object is new
|
||||
*
|
||||
* @return <?php echo $archiveTablePhpName ?> The archive object based on this object
|
||||
*/
|
||||
public function archive(ConnectionInterface $con = null)
|
||||
{
|
||||
if ($this->isNew()) {
|
||||
throw new PropelException('New objects cannot be archived. You must save the current object before calling archive().');
|
||||
}
|
||||
if (!$archive = $this->getArchive(<?php if (!$hasArchiveClass): ?>$con<?php endif; ?>)) {
|
||||
$archive = new <?php echo $archiveTablePhpName ?>();
|
||||
$archive->setPrimaryKey($this->getPrimaryKey());
|
||||
}
|
||||
$this->copyInto($archive, $deepCopy = false, $makeNew = false);
|
||||
<?php if ($archivedAtColumn): ?>
|
||||
$archive->set<?php echo $archivedAtColumn->getPhpName() ?>(time());
|
||||
<?php endif; ?>
|
||||
$archive->save(<?php if (!$hasArchiveClass): ?>$con<?php endif; ?>);
|
||||
|
||||
return $archive;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
/**
|
||||
* Removes the object from the database without archiving it.
|
||||
*
|
||||
* @param ConnectionInterface $con Optional connection object
|
||||
*
|
||||
* @return <?php echo $objectClassName ?> The current object (for fluent API support)
|
||||
*/
|
||||
public function deleteWithoutArchive(ConnectionInterface $con = null)
|
||||
{
|
||||
$this->archiveOnDelete = false;
|
||||
|
||||
return $this->delete($con);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
|
||||
/**
|
||||
* Get an archived version of the current object.
|
||||
*
|
||||
* @param ConnectionInterface $con Optional connection object
|
||||
*
|
||||
* @return <?php echo $archiveTablePhpName ?> An archive object, or null if the current object was never archived
|
||||
*/
|
||||
public function getArchive(ConnectionInterface $con = null)
|
||||
{
|
||||
if ($this->isNew()) {
|
||||
return null;
|
||||
}
|
||||
$archive = <?php echo $archiveTableQueryName ?>::create()
|
||||
->filterByPrimaryKey($this->getPrimaryKey())
|
||||
->findOne($con);
|
||||
|
||||
return $archive;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
/**
|
||||
* Populates the the current object based on a $archiveTablePhpName archive object.
|
||||
*
|
||||
* @param <?php echo $archiveTablePhpName ?> $archive An archived object based on the same class
|
||||
<?php if ($usesAutoIncrement): ?>
|
||||
* @param Boolean $populateAutoIncrementPrimaryKeys
|
||||
* If true, autoincrement columns are copied from the archive object.
|
||||
* If false, autoincrement columns are left intact.
|
||||
<?php endif; ?>
|
||||
*
|
||||
* @return <?php echo $objectClassName ?> The current object (for fluent API support)
|
||||
*/
|
||||
public function populateFromArchive($archive<?php if ($usesAutoIncrement): ?>, $populateAutoIncrementPrimaryKeys = false<?php endif; ?>) {
|
||||
<?php if ($usesAutoIncrement): ?>
|
||||
if ($populateAutoIncrementPrimaryKeys) {
|
||||
<?php foreach ($columns as $col): ?>
|
||||
<?php if ($col->isAutoIncrement()): ?>
|
||||
$this->set<?php echo $col->getPhpName() ?>($archive->get<?php echo $col->getPhpName() ?>());
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
}
|
||||
<?php endif; ?>
|
||||
<?php foreach ($columns as $col): ?>
|
||||
<?php if (!$col->isAutoIncrement()): ?>
|
||||
$this->set<?php echo $col->getPhpName() ?>($archive->get<?php echo $col->getPhpName() ?>());
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
|
||||
return $this;
|
||||
}
|
||||
17
core/vendor/propel/propel/src/Propel/Generator/Behavior/Archivable/templates/objectPreDelete.php
vendored
Normal file
17
core/vendor/propel/propel/src/Propel/Generator/Behavior/Archivable/templates/objectPreDelete.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php if ($isAddHooks) : ?>
|
||||
if ($ret) {
|
||||
if ($this->archiveOnDelete) {
|
||||
// do nothing yet. The object will be archived later when calling <?php echo $queryClassName ?>::delete().
|
||||
} else {
|
||||
$deleteQuery->setArchiveOnDelete(false);
|
||||
$this->archiveOnDelete = true;
|
||||
}
|
||||
}
|
||||
<?php else: ?>
|
||||
if ($this->archiveOnDelete) {
|
||||
// do nothing yet. The object will be archived later when calling <?php echo $queryClassName ?>::delete().
|
||||
} else {
|
||||
$deleteQuery->setArchiveOnDelete(false);
|
||||
$this->archiveOnDelete = true;
|
||||
}
|
||||
<?php endif;
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
/**
|
||||
* Revert the the current object to the state it had when it was last archived.
|
||||
* The object must be saved afterwards if the changes must persist.
|
||||
*
|
||||
* @param ConnectionInterface $con Optional connection object
|
||||
*
|
||||
* @throws PropelException If the object has no corresponding archive.
|
||||
*
|
||||
* @return <?php echo $objectClassName ?> The current object (for fluent API support)
|
||||
*/
|
||||
public function restoreFromArchive(ConnectionInterface $con = null)
|
||||
{
|
||||
if (!$archive = $this->getArchive($con)) {
|
||||
throw new PropelException('The current object has never been archived and cannot be restored');
|
||||
}
|
||||
$this->populateFromArchive($archive);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
/**
|
||||
* Persists the object to the database without archiving it.
|
||||
*
|
||||
* @param ConnectionInterface $con Optional connection object
|
||||
*
|
||||
* @return <?php echo $objectClassName ?> The current object (for fluent API support)
|
||||
*/
|
||||
public function saveWithoutArchive(ConnectionInterface $con = null)
|
||||
{
|
||||
<?php if (!$isArchiveOnInsert): ?>
|
||||
if (!$this->isNew()) {
|
||||
$this->archiveOnUpdate = false;
|
||||
}
|
||||
<?php elseif (!$isArchiveOnUpdate): ?>
|
||||
if ($this->isNew()) {
|
||||
$this->archiveOnInsert = false;
|
||||
}
|
||||
<?php else: ?>
|
||||
if ($this->isNew()) {
|
||||
$this->archiveOnInsert = false;
|
||||
} else {
|
||||
$this->archiveOnUpdate = false;
|
||||
}
|
||||
<?php endif; ?>
|
||||
|
||||
return $this->save($con);
|
||||
}
|
||||
42
core/vendor/propel/propel/src/Propel/Generator/Behavior/Archivable/templates/queryArchive.php
vendored
Normal file
42
core/vendor/propel/propel/src/Propel/Generator/Behavior/Archivable/templates/queryArchive.php
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
/**
|
||||
* Copy the data of the objects satisfying the query into <?php echo $archiveTablePhpName ?> archive objects.
|
||||
* The archived objects are then saved.
|
||||
* If any of the objects has already been archived, the archived object
|
||||
* is updated and not duplicated.
|
||||
* Warning: This termination methods issues 2n+1 queries.
|
||||
*
|
||||
* @param ConnectionInterface $con Connection to use.
|
||||
* @param Boolean $useLittleMemory Whether or not to use OnDemandFormatter to retrieve objects.
|
||||
* Set to false if the identity map matters.
|
||||
* Set to true (default) to use less memory.
|
||||
*
|
||||
* @return int the number of archived objects
|
||||
*/
|
||||
public function archive($con = null, $useLittleMemory = true)
|
||||
{
|
||||
$totalArchivedObjects = 0;
|
||||
$criteria = clone $this;
|
||||
// prepare the query
|
||||
$criteria->setWith(array());
|
||||
if ($useLittleMemory) {
|
||||
$criteria->setFormatter(ModelCriteria::FORMAT_ON_DEMAND);
|
||||
}
|
||||
if ($con === null) {
|
||||
$con = Propel::getServiceContainer()->getWriteConnection(<?php echo $modelTableMap ?>::DATABASE_NAME);
|
||||
}
|
||||
$con->beginTransaction();
|
||||
try {
|
||||
// archive all results one by one
|
||||
foreach ($criteria->find($con) as $object) {
|
||||
$object->archive($con);
|
||||
$totalArchivedObjects++;
|
||||
}
|
||||
$con->commit();
|
||||
} catch (PropelException $e) {
|
||||
$con->rollBack();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return $totalArchivedObjects;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
/**
|
||||
* Delete records matching the current query without archiving them.
|
||||
*
|
||||
* @param ConnectionInterface $con Connection to use.
|
||||
*
|
||||
* @return integer the number of deleted rows
|
||||
*/
|
||||
public function deleteWithoutArchive($con = null)
|
||||
{
|
||||
$this->archiveOnDelete = false;
|
||||
|
||||
return $this->delete($con);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all records without archiving them.
|
||||
*
|
||||
* @param ConnectionInterface $con Connection to use.
|
||||
*
|
||||
* @return integer the number of deleted rows
|
||||
*/
|
||||
public function deleteAllWithoutArchive($con = null)
|
||||
{
|
||||
$this->archiveOnDelete = false;
|
||||
|
||||
return $this->deleteAll($con);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
/**
|
||||
* Enable/disable auto-archiving on delete for the next query.
|
||||
*
|
||||
* @param boolean True if the query must archive deleted objects, false otherwise.
|
||||
*/
|
||||
public function setArchiveOnDelete($archiveOnDelete)
|
||||
{
|
||||
$this->archiveOnDelete = $archiveOnDelete;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
/**
|
||||
* Enable/disable auto-archiving on update for the next query.
|
||||
*
|
||||
* @param boolean True if the query must archive updated objects, false otherwise.
|
||||
*/
|
||||
public function setArchiveOnUpdate($archiveOnUpdate)
|
||||
{
|
||||
$this->archiveOnUpdate = $archiveOnUpdate;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
/**
|
||||
* Delete records matching the current query without archiving them.
|
||||
*
|
||||
* @param array $values Associative array of keys and values to replace
|
||||
* @param ConnectionInterface $con an optional connection object
|
||||
* @param boolean $forceIndividualSaves If false (default), the resulting call is a Criteria::doUpdate(), ortherwise it is a series of save() calls on all the found objects
|
||||
*
|
||||
* @return integer the number of deleted rows
|
||||
*/
|
||||
public function updateWithoutArchive($values, $con = null, $forceIndividualSaves = false)
|
||||
{
|
||||
$this->archiveOnUpdate = false;
|
||||
|
||||
return $this->update($values, $con, $forceIndividualSaves);
|
||||
}
|
||||
54
core/vendor/propel/propel/src/Propel/Generator/Behavior/AutoAddPk/AutoAddPkBehavior.php
vendored
Normal file
54
core/vendor/propel/propel/src/Propel/Generator/Behavior/AutoAddPk/AutoAddPkBehavior.php
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
<?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\Behavior\AutoAddPk;
|
||||
|
||||
use Propel\Generator\Model\Behavior;
|
||||
|
||||
/**
|
||||
* Adds a primary key to models defined without one
|
||||
*
|
||||
* @author François Zaninotto
|
||||
*/
|
||||
class AutoAddPkBehavior extends Behavior
|
||||
{
|
||||
// default parameters value
|
||||
protected $parameters = array(
|
||||
'name' => 'id',
|
||||
'autoIncrement' => 'true',
|
||||
'type' => 'INTEGER'
|
||||
);
|
||||
|
||||
/**
|
||||
* Copy the behavior to the database tables
|
||||
* Only for tables that have no Pk
|
||||
*/
|
||||
public function modifyDatabase()
|
||||
{
|
||||
foreach ($this->getDatabase()->getTables() as $table) {
|
||||
if (!$table->hasPrimaryKey()) {
|
||||
$b = clone $this;
|
||||
$table->addBehavior($b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the primary key to the current table
|
||||
*/
|
||||
public function modifyTable()
|
||||
{
|
||||
$table = $this->getTable();
|
||||
if (!$table->hasPrimaryKey() && !$table->hasBehavior('concrete_inheritance')) {
|
||||
$columnAttributes = array_merge(array('primaryKey' => 'true'), $this->getParameters());
|
||||
$this->getTable()->addColumn($columnAttributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,252 @@
|
||||
<?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\Behavior\ConcreteInheritance;
|
||||
|
||||
use Propel\Generator\Model\Behavior;
|
||||
use Propel\Generator\Model\ForeignKey;
|
||||
|
||||
/**
|
||||
* Makes a model inherit another one. The model with this behavior gets a copy
|
||||
* of the structure of the parent model. In addition, both the ActiveRecord and
|
||||
* ActiveQuery classes will extend the related classes of the parent model.
|
||||
* Lastly (an optionally), the data from a model with this behavior is copied
|
||||
* to the parent model.
|
||||
*
|
||||
* @author François Zaninotto
|
||||
*/
|
||||
class ConcreteInheritanceBehavior extends Behavior
|
||||
{
|
||||
// default parameters value
|
||||
protected $parameters = array(
|
||||
'extends' => '',
|
||||
'descendant_column' => 'descendant_class',
|
||||
'copy_data_to_parent' => 'true',
|
||||
'schema' => ''
|
||||
);
|
||||
|
||||
public function modifyTable()
|
||||
{
|
||||
$table = $this->getTable();
|
||||
$parentTable = $this->getParentTable();
|
||||
|
||||
if ($this->isCopyData()) {
|
||||
// tell the parent table that it has a descendant
|
||||
if (!$parentTable->hasBehavior('concrete_inheritance_parent')) {
|
||||
$parentBehavior = new ConcreteInheritanceParentBehavior();
|
||||
$parentBehavior->setName('concrete_inheritance_parent');
|
||||
$parentBehavior->addParameter(array('name' => 'descendant_column', 'value' => $this->getParameter('descendant_column')));
|
||||
$parentTable->addBehavior($parentBehavior);
|
||||
// The parent table's behavior modifyTable() must be executed before this one
|
||||
$parentBehavior->getTableModifier()->modifyTable();
|
||||
$parentBehavior->setTableModified(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the columns of the parent table
|
||||
foreach ($parentTable->getColumns() as $column) {
|
||||
if ($column->getName() == $this->getParameter('descendant_column')) {
|
||||
continue;
|
||||
}
|
||||
if ($table->hasColumn($column->getName())) {
|
||||
continue;
|
||||
}
|
||||
$copiedColumn = clone $column;
|
||||
if ($column->isAutoIncrement() && $this->isCopyData()) {
|
||||
$copiedColumn->setAutoIncrement(false);
|
||||
}
|
||||
$table->addColumn($copiedColumn);
|
||||
if ($column->isPrimaryKey() && $this->isCopyData()) {
|
||||
$fk = new ForeignKey();
|
||||
$fk->setForeignTableCommonName($column->getTable()->getCommonName());
|
||||
$fk->setForeignSchemaName($column->getTable()->getSchema());
|
||||
$fk->setOnDelete('CASCADE');
|
||||
$fk->setOnUpdate(null);
|
||||
$fk->addReference($copiedColumn, $column);
|
||||
$fk->isParentChild = true;
|
||||
$table->addForeignKey($fk);
|
||||
}
|
||||
}
|
||||
|
||||
// add the foreign keys of the parent table
|
||||
foreach ($parentTable->getForeignKeys() as $fk) {
|
||||
$copiedFk = clone $fk;
|
||||
$copiedFk->setName('');
|
||||
$copiedFk->setRefPhpName('');
|
||||
$this->getTable()->addForeignKey($copiedFk);
|
||||
}
|
||||
|
||||
// add the indices of the parent table
|
||||
foreach ($parentTable->getIndices() as $index) {
|
||||
$copiedIndex = clone $index;
|
||||
$copiedIndex->setName('');
|
||||
$this->getTable()->addIndex($copiedIndex);
|
||||
}
|
||||
|
||||
// add the unique indices of the parent table
|
||||
foreach ($parentTable->getUnices() as $unique) {
|
||||
$copiedUnique = clone $unique;
|
||||
$copiedUnique->setName('');
|
||||
$this->getTable()->addUnique($copiedUnique);
|
||||
}
|
||||
|
||||
// add the Behaviors of the parent table
|
||||
foreach ($parentTable->getBehaviors() as $behavior) {
|
||||
if ($behavior->getName() == 'concrete_inheritance_parent' || $behavior->getName() == 'concrete_inheritance') {
|
||||
continue;
|
||||
}
|
||||
// validate behavior. If validate behavior already exists, clone only rules from parent
|
||||
if ('validate' === $behavior->getName() && $table->hasBehavior('validate')) {
|
||||
$table->getBehavior('validate')->mergeParameters($behavior->getParameters());
|
||||
|
||||
continue;
|
||||
}
|
||||
$copiedBehavior = clone $behavior;
|
||||
$copiedBehavior->setTableModified(false);
|
||||
$this->getTable()->addBehavior($copiedBehavior);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected function getParentTable()
|
||||
{
|
||||
$database = $this->getTable()->getDatabase();
|
||||
$tableName = $database->getTablePrefix() . $this->getParameter('extends');
|
||||
if ($database->getPlatform()->supportsSchemas() && $this->getParameter('schema')) {
|
||||
$tableName = $this->getParameter('schema').$database->getPlatform()->getSchemaDelimiter().$tableName;
|
||||
}
|
||||
|
||||
return $database->getTable($tableName);
|
||||
}
|
||||
|
||||
protected function isCopyData()
|
||||
{
|
||||
return 'true' === $this->getParameter('copy_data_to_parent');
|
||||
}
|
||||
|
||||
public function parentClass($builder)
|
||||
{
|
||||
$parentTable = $this->getParentTable();
|
||||
switch (get_class($builder)) {
|
||||
case 'Propel\Generator\Builder\Om\ObjectBuilder':
|
||||
return $builder->declareClassFromBuilder($builder->getNewStubObjectBuilder($parentTable), true);
|
||||
case 'Propel\Generator\Builder\Om\QueryBuilder':
|
||||
return $builder->declareClassFromBuilder($builder->getNewStubQueryBuilder($parentTable), true);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function preSave($script)
|
||||
{
|
||||
if ($this->isCopyData()) {
|
||||
return "\$parent = \$this->getSyncParent(\$con);
|
||||
\$parent->save(\$con);
|
||||
\$this->setPrimaryKey(\$parent->getPrimaryKey());
|
||||
";
|
||||
}
|
||||
}
|
||||
|
||||
public function postDelete($script)
|
||||
{
|
||||
if ($this->isCopyData()) {
|
||||
return "\$this->getParentOrCreate(\$con)->delete(\$con);
|
||||
";
|
||||
}
|
||||
}
|
||||
|
||||
public function objectMethods($builder)
|
||||
{
|
||||
if (!$this->isCopyData()) {
|
||||
return;
|
||||
}
|
||||
$this->builder = $builder;
|
||||
$script = '';
|
||||
$this->addObjectGetParentOrCreate($script);
|
||||
$this->addObjectGetSyncParent($script);
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
protected function addObjectGetParentOrCreate(&$script)
|
||||
{
|
||||
$parentTable = $this->getParentTable();
|
||||
$parentClass = $this->builder->getClassNameFromBuilder($this->builder->getNewStubObjectBuilder($parentTable));
|
||||
$script .= "
|
||||
/**
|
||||
* Get or Create the parent " . $parentClass . " object of the current object
|
||||
*
|
||||
* @return " . $parentClass . " The parent object
|
||||
*/
|
||||
public function getParentOrCreate(\$con = null)
|
||||
{
|
||||
if (\$this->isNew()) {
|
||||
if (\$this->isPrimaryKeyNull()) {
|
||||
\$parent = new " . $parentClass . "();
|
||||
\$parent->set" . $this->getParentTable()->getColumn($this->getParameter('descendant_column'))->getPhpName() . "('" . $this->builder->getStubObjectBuilder()->getQualifiedClassName() . "');
|
||||
|
||||
return \$parent;
|
||||
} else {
|
||||
\$parent = " . $this->builder->getNewStubQueryBuilder($parentTable)->getClassname() . "::create()->findPk(\$this->getPrimaryKey(), \$con);
|
||||
if (null === \$parent || null !== \$parent->getDescendantClass()) {
|
||||
\$parent = new " . $parentClass . "();
|
||||
\$parent->setPrimaryKey(\$this->getPrimaryKey());
|
||||
\$parent->set" . $this->getParentTable()->getColumn($this->getParameter('descendant_column'))->getPhpName() . "('" . $this->builder->getStubObjectBuilder()->getQualifiedClassName() . "');
|
||||
}
|
||||
|
||||
return \$parent;
|
||||
}
|
||||
} else {
|
||||
return " . $this->builder->getClassNameFromBuilder($this->builder->getNewStubQueryBuilder($parentTable)) . "::create()->findPk(\$this->getPrimaryKey(), \$con);
|
||||
}
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addObjectGetSyncParent(&$script)
|
||||
{
|
||||
$parentTable = $this->getParentTable();
|
||||
$pkeys = $parentTable->getPrimaryKey();
|
||||
$cptype = $pkeys[0]->getPhpType();
|
||||
$script .= "
|
||||
/**
|
||||
* Create or Update the parent " . $parentTable->getPhpName() . " object
|
||||
* And return its primary key
|
||||
*
|
||||
* @return " . $cptype . " The primary key of the parent object
|
||||
*/
|
||||
public function getSyncParent(\$con = null)
|
||||
{
|
||||
\$parent = \$this->getParentOrCreate(\$con);";
|
||||
foreach ($parentTable->getColumns() as $column) {
|
||||
if ($column->isPrimaryKey() || $column->getName() == $this->getParameter('descendant_column')) {
|
||||
continue;
|
||||
}
|
||||
$phpName = $column->getPhpName();
|
||||
$script .= "
|
||||
\$parent->set{$phpName}(\$this->get{$phpName}());";
|
||||
}
|
||||
foreach ($parentTable->getForeignKeys() as $fk) {
|
||||
if (isset($fk->isParentChild) && $fk->isParentChild) {
|
||||
continue;
|
||||
}
|
||||
$refPhpName = $this->builder->getFKPhpNameAffix($fk, false);
|
||||
$script .= "
|
||||
if (\$this->get" . $refPhpName . "() && \$this->get" . $refPhpName . "()->isNew()) {
|
||||
\$parent->set" . $refPhpName . "(\$this->get" . $refPhpName . "());
|
||||
}";
|
||||
}
|
||||
$script .= "
|
||||
|
||||
return \$parent;
|
||||
}
|
||||
";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
<?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\Behavior\ConcreteInheritance;
|
||||
|
||||
use Propel\Generator\Model\Behavior;
|
||||
|
||||
/**
|
||||
* Symmetrical behavior of the concrete_inheritance. When model A extends model B,
|
||||
* model A gets the concrete_inheritance behavior, and model B gets the
|
||||
* concrete_inheritance_parent
|
||||
*
|
||||
* @author François Zaninotto
|
||||
*/
|
||||
class ConcreteInheritanceParentBehavior extends Behavior
|
||||
{
|
||||
// default parameters value
|
||||
protected $parameters = array(
|
||||
'descendant_column' => 'descendant_class'
|
||||
);
|
||||
|
||||
public function modifyTable()
|
||||
{
|
||||
$table = $this->getTable();
|
||||
if (!$table->hasColumn($this->getParameter('descendant_column'))) {
|
||||
$table->addColumn(array(
|
||||
'name' => $this->getParameter('descendant_column'),
|
||||
'type' => 'VARCHAR',
|
||||
'size' => 100
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
protected function getColumnGetter()
|
||||
{
|
||||
return 'get' . $this->getColumnForParameter('descendant_column')->getPhpName();
|
||||
}
|
||||
|
||||
public function objectMethods($builder)
|
||||
{
|
||||
$this->builder = $builder;
|
||||
$this->builder->declareClasses('Propel\Runtime\ActiveQuery\PropelQuery');
|
||||
$script = '';
|
||||
$this->addHasChildObject($script);
|
||||
$this->addGetChildObject($script);
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
protected function addHasChildObject(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Whether or not this object is the parent of a child object
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasChildObject()
|
||||
{
|
||||
return \$this->" . $this->getColumnGetter() . "() !== null;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addGetChildObject(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Get the child object of this object
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getChildObject()
|
||||
{
|
||||
if (!\$this->hasChildObject()) {
|
||||
return null;
|
||||
}
|
||||
\$childObjectClass = \$this->" . $this->getColumnGetter() . "();
|
||||
\$childObject = PropelQuery::from(\$childObjectClass)->findPk(\$this->getPrimaryKey());
|
||||
|
||||
return \$childObject->hasChildObject() ? \$childObject->getChildObject() : \$childObject;
|
||||
}
|
||||
";
|
||||
}
|
||||
}
|
||||
139
core/vendor/propel/propel/src/Propel/Generator/Behavior/Delegate/DelegateBehavior.php
vendored
Normal file
139
core/vendor/propel/propel/src/Propel/Generator/Behavior/Delegate/DelegateBehavior.php
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
<?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\Behavior\Delegate;
|
||||
|
||||
use Propel\Generator\Model\Behavior;
|
||||
use Propel\Generator\Model\ForeignKey;
|
||||
|
||||
/**
|
||||
* Gives a model class the ability to delegate methods to a relationship.
|
||||
*
|
||||
* @author François Zaninotto
|
||||
*/
|
||||
class DelegateBehavior extends Behavior
|
||||
{
|
||||
const ONE_TO_ONE = 1;
|
||||
const MANY_TO_ONE = 2;
|
||||
|
||||
// default parameters value
|
||||
protected $parameters = array(
|
||||
'to' => ''
|
||||
);
|
||||
|
||||
protected $delegates = array();
|
||||
|
||||
/**
|
||||
* Lists the delegates and checks that the behavior can use them,
|
||||
* And adds a fk from the delegate to the main table if not already set
|
||||
*/
|
||||
public function modifyTable()
|
||||
{
|
||||
$table = $this->getTable();
|
||||
$database = $table->getDatabase();
|
||||
$delegates = explode(',', $this->parameters['to']);
|
||||
foreach ($delegates as $delegate) {
|
||||
$delegate = $database->getTablePrefix() . trim($delegate);
|
||||
if (!$database->hasTable($delegate)) {
|
||||
throw new \InvalidArgumentException(sprintf(
|
||||
'No delegate table "%s" found for table "%s"',
|
||||
$delegate,
|
||||
$table->getName()
|
||||
));
|
||||
}
|
||||
if (in_array($delegate, $table->getForeignTableNames())) {
|
||||
// existing many-to-one relationship
|
||||
$type = self::MANY_TO_ONE;
|
||||
} else {
|
||||
// one_to_one relationship
|
||||
$delegateTable = $this->getDelegateTable($delegate);
|
||||
if (in_array($table->getName(), $delegateTable->getForeignTableNames())) {
|
||||
// existing one-to-one relationship
|
||||
$fks = $delegateTable->getForeignKeysReferencingTable($this->getTable()->getName());
|
||||
$fk = $fks[0];
|
||||
if (!$fk->isLocalPrimaryKey()) {
|
||||
throw new \InvalidArgumentException(sprintf(
|
||||
'Delegate table "%s" has a relationship with table "%s", but it\'s a one-to-many relationship. The `delegate` behavior only supports one-to-one relationships in this case.',
|
||||
$delegate,
|
||||
$table->getName()
|
||||
));
|
||||
}
|
||||
} else {
|
||||
// no relationship yet: must be created
|
||||
$this->relateDelegateToMainTable($this->getDelegateTable($delegate), $table);
|
||||
}
|
||||
$type = self::ONE_TO_ONE;
|
||||
}
|
||||
$this->delegates[$delegate] = $type;
|
||||
}
|
||||
}
|
||||
|
||||
protected function relateDelegateToMainTable($delegateTable, $mainTable)
|
||||
{
|
||||
$pks = $mainTable->getPrimaryKey();
|
||||
foreach ($pks as $column) {
|
||||
$mainColumnName = $column->getName();
|
||||
if (!$delegateTable->hasColumn($mainColumnName)) {
|
||||
$column = clone $column;
|
||||
$column->setAutoIncrement(false);
|
||||
$delegateTable->addColumn($column);
|
||||
}
|
||||
}
|
||||
// Add a one-to-one fk
|
||||
$fk = new ForeignKey();
|
||||
$fk->setForeignTableCommonName($mainTable->getCommonName());
|
||||
$fk->setForeignSchemaName($mainTable->getSchema());
|
||||
$fk->setDefaultJoin('LEFT JOIN');
|
||||
$fk->setOnDelete(ForeignKey::CASCADE);
|
||||
$fk->setOnUpdate(ForeignKey::NONE);
|
||||
foreach ($pks as $column) {
|
||||
$fk->addReference($column->getName(), $column->getName());
|
||||
}
|
||||
$delegateTable->addForeignKey($fk);
|
||||
}
|
||||
|
||||
protected function getDelegateTable($delegateTableName)
|
||||
{
|
||||
return $this->getTable()->getDatabase()->getTable($delegateTableName);
|
||||
}
|
||||
|
||||
public function objectCall($builder)
|
||||
{
|
||||
$plural = false;
|
||||
$script = '';
|
||||
foreach ($this->delegates as $delegate => $type) {
|
||||
$delegateTable = $this->getDelegateTable($delegate);
|
||||
if ($type == self::ONE_TO_ONE) {
|
||||
$fks = $delegateTable->getForeignKeysReferencingTable($this->getTable()->getName());
|
||||
$fk = $fks[0];
|
||||
$ARClassName = $builder->getClassNameFromBuilder($builder->getNewStubObjectBuilder($fk->getTable()));
|
||||
$ARFQCN = $builder->getNewStubObjectBuilder($fk->getTable())->getFullyQualifiedClassName();
|
||||
$relationName = $builder->getRefFKPhpNameAffix($fk, $plural);
|
||||
} else {
|
||||
$fks = $this->getTable()->getForeignKeysReferencingTable($delegate);
|
||||
$fk = $fks[0];
|
||||
$ARClassName = $builder->getClassNameFromBuilder($builder->getNewStubObjectBuilder($delegateTable));
|
||||
$ARFQCN = $builder->getNewStubObjectBuilder($delegateTable)->getFullyQualifiedClassName();
|
||||
$relationName = $builder->getFKPhpNameAffix($fk);
|
||||
}
|
||||
$script .= "
|
||||
if (is_callable(array('$ARFQCN', \$name))) {
|
||||
if (!\$delegate = \$this->get$relationName()) {
|
||||
\$delegate = new $ARClassName();
|
||||
\$this->set$relationName(\$delegate);
|
||||
}
|
||||
|
||||
return call_user_func_array(array(\$delegate, \$name), \$params);
|
||||
}";
|
||||
}
|
||||
|
||||
return $script;
|
||||
}
|
||||
}
|
||||
304
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/I18nBehavior.php
vendored
Normal file
304
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/I18nBehavior.php
vendored
Normal file
@@ -0,0 +1,304 @@
|
||||
<?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\Behavior\I18n;
|
||||
|
||||
use Propel\Generator\Exception\EngineException;
|
||||
use Propel\Generator\Model\Behavior;
|
||||
use Propel\Generator\Model\ForeignKey;
|
||||
use Propel\Generator\Model\PropelTypes;
|
||||
use Propel\Generator\Behavior\Validate\ValidateBehavior;
|
||||
|
||||
/**
|
||||
* Allows translation of text columns through transparent one-to-many
|
||||
* relationship.
|
||||
*
|
||||
* @author Francois Zaninotto
|
||||
*/
|
||||
class I18nBehavior extends Behavior
|
||||
{
|
||||
const DEFAULT_LOCALE = 'en_US';
|
||||
|
||||
// default parameters value
|
||||
protected $parameters = array(
|
||||
'i18n_table' => '%TABLE%_i18n',
|
||||
'i18n_phpname' => '%PHPNAME%I18n',
|
||||
'i18n_columns' => '',
|
||||
'locale_column' => 'locale',
|
||||
'locale_length' => 5,
|
||||
'default_locale' => null,
|
||||
'locale_alias' => '',
|
||||
);
|
||||
|
||||
protected $tableModificationOrder = 70;
|
||||
|
||||
protected $objectBuilderModifier;
|
||||
|
||||
protected $queryBuilderModifier;
|
||||
|
||||
protected $i18nTable;
|
||||
|
||||
public function modifyDatabase()
|
||||
{
|
||||
foreach ($this->getDatabase()->getTables() as $table) {
|
||||
if ($table->hasBehavior('i18n') && !$table->getBehavior('i18n')->getParameter('default_locale')) {
|
||||
$table->getBehavior('i18n')->addParameter(array(
|
||||
'name' => 'default_locale',
|
||||
'value' => $this->getParameter('default_locale'),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getDefaultLocale()
|
||||
{
|
||||
if (!$defaultLocale = $this->getParameter('default_locale')) {
|
||||
$defaultLocale = self::DEFAULT_LOCALE;
|
||||
}
|
||||
|
||||
return $defaultLocale;
|
||||
}
|
||||
|
||||
public function getI18nTable()
|
||||
{
|
||||
return $this->i18nTable;
|
||||
}
|
||||
|
||||
public function getI18nForeignKey()
|
||||
{
|
||||
foreach ($this->i18nTable->getForeignKeys() as $fk) {
|
||||
if ($fk->getForeignTableName() == $this->table->getName()) {
|
||||
return $fk;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getLocaleColumn()
|
||||
{
|
||||
return $this->getI18nTable()->getColumn($this->getLocaleColumnName());
|
||||
}
|
||||
|
||||
public function getI18nColumns()
|
||||
{
|
||||
$columns = array();
|
||||
$i18nTable = $this->getI18nTable();
|
||||
if ($columnNames = $this->getI18nColumnNamesFromConfig()) {
|
||||
// Strategy 1: use the i18n_columns parameter
|
||||
foreach ($columnNames as $columnName) {
|
||||
$columns []= $i18nTable->getColumn($columnName);
|
||||
}
|
||||
} else {
|
||||
// strategy 2: use the columns of the i18n table
|
||||
// warning: does not work when database behaviors add columns to all tables
|
||||
// (such as timestampable behavior)
|
||||
foreach ($i18nTable->getColumns() as $column) {
|
||||
if (!$column->isPrimaryKey()) {
|
||||
$columns []= $column;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
public function replaceTokens($string)
|
||||
{
|
||||
$table = $this->getTable();
|
||||
|
||||
return strtr($string, array(
|
||||
'%TABLE%' => $table->getName(),
|
||||
'%PHPNAME%' => $table->getPhpName(),
|
||||
));
|
||||
}
|
||||
|
||||
public function getObjectBuilderModifier()
|
||||
{
|
||||
if (null === $this->objectBuilderModifier) {
|
||||
$this->objectBuilderModifier = new I18nBehaviorObjectBuilderModifier($this);
|
||||
}
|
||||
|
||||
return $this->objectBuilderModifier;
|
||||
}
|
||||
|
||||
public function getQueryBuilderModifier()
|
||||
{
|
||||
if (null === $this->queryBuilderModifier) {
|
||||
$this->queryBuilderModifier = new I18nBehaviorQueryBuilderModifier($this);
|
||||
}
|
||||
|
||||
return $this->queryBuilderModifier;
|
||||
}
|
||||
|
||||
public function staticAttributes($builder)
|
||||
{
|
||||
return $this->renderTemplate('staticAttributes', array(
|
||||
'defaultLocale' => $this->getDefaultLocale(),
|
||||
));
|
||||
}
|
||||
|
||||
public function modifyTable()
|
||||
{
|
||||
$this->addI18nTable();
|
||||
$this->relateI18nTableToMainTable();
|
||||
$this->addLocaleColumnToI18n();
|
||||
$this->moveI18nColumns();
|
||||
}
|
||||
|
||||
protected function addI18nTable()
|
||||
{
|
||||
$table = $this->getTable();
|
||||
$database = $table->getDatabase();
|
||||
$i18nTableName = $this->getI18nTableName();
|
||||
|
||||
if ($database->hasTable($i18nTableName)) {
|
||||
$this->i18nTable = $database->getTable($i18nTableName);
|
||||
} else {
|
||||
$this->i18nTable = $database->addTable(array(
|
||||
'name' => $i18nTableName,
|
||||
'phpName' => $this->getI18nTablePhpName(),
|
||||
'package' => $table->getPackage(),
|
||||
'schema' => $table->getSchema(),
|
||||
'namespace' => $table->getNamespace() ? '\\' . $table->getNamespace() : null,
|
||||
'skipSql' => $table->isSkipSql()
|
||||
));
|
||||
|
||||
// every behavior adding a table should re-execute database behaviors
|
||||
foreach ($database->getBehaviors() as $behavior) {
|
||||
$behavior->modifyDatabase();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function relateI18nTableToMainTable()
|
||||
{
|
||||
$table = $this->getTable();
|
||||
$i18nTable = $this->i18nTable;
|
||||
$pks = $this->getTable()->getPrimaryKey();
|
||||
|
||||
if (count($pks) > 1) {
|
||||
throw new EngineException('The i18n behavior does not support tables with composite primary keys');
|
||||
}
|
||||
|
||||
foreach ($pks as $column) {
|
||||
if (!$i18nTable->hasColumn($column->getName())) {
|
||||
$column = clone $column;
|
||||
$column->setAutoIncrement(false);
|
||||
$i18nTable->addColumn($column);
|
||||
}
|
||||
}
|
||||
|
||||
if (in_array($table->getName(), $i18nTable->getForeignTableNames())) {
|
||||
return;
|
||||
}
|
||||
|
||||
$fk = new ForeignKey();
|
||||
$fk->setForeignTableCommonName($table->getCommonName());
|
||||
$fk->setForeignSchemaName($table->getSchema());
|
||||
$fk->setDefaultJoin('LEFT JOIN');
|
||||
$fk->setOnDelete(ForeignKey::CASCADE);
|
||||
$fk->setOnUpdate(ForeignKey::NONE);
|
||||
|
||||
foreach ($pks as $column) {
|
||||
$fk->addReference($column->getName(), $column->getName());
|
||||
}
|
||||
|
||||
$i18nTable->addForeignKey($fk);
|
||||
}
|
||||
|
||||
protected function addLocaleColumnToI18n()
|
||||
{
|
||||
$localeColumnName = $this->getLocaleColumnName();
|
||||
|
||||
if (! $this->i18nTable->hasColumn($localeColumnName)) {
|
||||
$this->i18nTable->addColumn(array(
|
||||
'name' => $localeColumnName,
|
||||
'type' => PropelTypes::VARCHAR,
|
||||
'size' => $this->getParameter('locale_length') ? (int) $this->getParameter('locale_length') : 5,
|
||||
'default' => $this->getDefaultLocale(),
|
||||
'primaryKey' => 'true',
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves i18n columns from the main table to the i18n table
|
||||
*/
|
||||
protected function moveI18nColumns()
|
||||
{
|
||||
$table = $this->getTable();
|
||||
$i18nTable = $this->i18nTable;
|
||||
|
||||
$i18nValidateParams = array();
|
||||
foreach ($this->getI18nColumnNamesFromConfig() as $columnName) {
|
||||
if (!$i18nTable->hasColumn($columnName)) {
|
||||
if (!$table->hasColumn($columnName)) {
|
||||
throw new EngineException(sprintf('No column named %s found in table %s', $columnName, $table->getName()));
|
||||
}
|
||||
|
||||
$column = $table->getColumn($columnName);
|
||||
$i18nTable->addColumn(clone $column);
|
||||
|
||||
// validate behavior: move rules associated to the column
|
||||
if ($table->hasBehavior('validate')) {
|
||||
$validateBehavior = $table->getBehavior('validate');
|
||||
$params = $validateBehavior->getParametersFromColumnName($columnName);
|
||||
$i18nValidateParams = array_merge($i18nValidateParams, $params);
|
||||
$validateBehavior->removeParametersFromColumnName($columnName);
|
||||
}
|
||||
// FIXME: also move FKs, and indices on this column
|
||||
}
|
||||
|
||||
if ($table->hasColumn($columnName)) {
|
||||
$table->removeColumn($columnName);
|
||||
}
|
||||
}
|
||||
|
||||
// validate behavior
|
||||
if (count($i18nValidateParams) > 0) {
|
||||
$i18nVbehavior = new ValidateBehavior();
|
||||
$i18nVbehavior->setName('validate');
|
||||
$i18nVbehavior->setParameters($i18nValidateParams);
|
||||
$i18nTable->addBehavior($i18nVbehavior);
|
||||
|
||||
// current table must have almost 1 validation rule
|
||||
$validate = $table->getBehavior('validate');
|
||||
$validate->addRuleOnPk();
|
||||
}
|
||||
}
|
||||
|
||||
protected function getI18nTableName()
|
||||
{
|
||||
return $this->replaceTokens($this->getParameter('i18n_table'));
|
||||
}
|
||||
|
||||
protected function getI18nTablePhpName()
|
||||
{
|
||||
return $this->replaceTokens($this->getParameter('i18n_phpname'));
|
||||
}
|
||||
|
||||
protected function getLocaleColumnName()
|
||||
{
|
||||
return $this->replaceTokens($this->getParameter('locale_column'));
|
||||
}
|
||||
|
||||
protected function getI18nColumnNamesFromConfig()
|
||||
{
|
||||
$columnNames = explode(',', $this->getParameter('i18n_columns'));
|
||||
foreach ($columnNames as $key => $columnName) {
|
||||
if ($columnName = trim($columnName)) {
|
||||
$columnNames[$key] = $columnName;
|
||||
} else {
|
||||
unset($columnNames[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
return $columnNames;
|
||||
}
|
||||
}
|
||||
234
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/I18nBehaviorObjectBuilderModifier.php
vendored
Normal file
234
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/I18nBehaviorObjectBuilderModifier.php
vendored
Normal file
@@ -0,0 +1,234 @@
|
||||
<?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\Behavior\I18n;
|
||||
|
||||
use Propel\Generator\Model\Column;
|
||||
use Propel\Generator\Model\PropelTypes;
|
||||
|
||||
/**
|
||||
* Allows translation of text columns through transparent one-to-many relationship.
|
||||
* Modifier for the object builder.
|
||||
*
|
||||
* @author François Zaninotto
|
||||
*/
|
||||
class I18nBehaviorObjectBuilderModifier
|
||||
{
|
||||
protected $behavior;
|
||||
protected $table;
|
||||
protected $builder;
|
||||
|
||||
public function __construct($behavior)
|
||||
{
|
||||
$this->behavior = $behavior;
|
||||
$this->table = $behavior->getTable();
|
||||
}
|
||||
|
||||
public function postDelete($builder)
|
||||
{
|
||||
$this->builder = $builder;
|
||||
if (!$builder->getPlatform()->supportsNativeDeleteTrigger() && !$builder->getBuildProperty('emulateForeignKeyConstraints')) {
|
||||
$i18nTable = $this->behavior->getI18nTable();
|
||||
|
||||
return $this->behavior->renderTemplate('objectPostDelete', array(
|
||||
'i18nQueryName' => $builder->getClassNameFromBuilder($builder->getNewStubQueryBuilder($i18nTable)),
|
||||
'objectClassName' => $builder->getNewStubObjectBuilder($this->behavior->getTable())->getUnqualifiedClassName(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
public function objectAttributes($builder)
|
||||
{
|
||||
return $this->behavior->renderTemplate('objectAttributes', array(
|
||||
'defaultLocale' => $this->behavior->getDefaultLocale(),
|
||||
'objectClassName' => $builder->getClassNameFromBuilder($builder->getNewStubObjectBuilder($this->behavior->getI18nTable())),
|
||||
));
|
||||
}
|
||||
|
||||
public function objectClearReferences($builder)
|
||||
{
|
||||
return $this->behavior->renderTemplate('objectClearReferences', array(
|
||||
'defaultLocale' => $this->behavior->getDefaultLocale(),
|
||||
));
|
||||
}
|
||||
|
||||
public function objectMethods($builder)
|
||||
{
|
||||
$this->builder = $builder;
|
||||
|
||||
$script = '';
|
||||
$script .= $this->addSetLocale();
|
||||
$script .= $this->addGetLocale();
|
||||
|
||||
if ($alias = $this->behavior->getParameter('locale_alias')) {
|
||||
$script .= $this->addGetLocaleAlias($alias);
|
||||
$script .= $this->addSetLocaleAlias($alias);
|
||||
}
|
||||
|
||||
$script .= $this->addGetTranslation();
|
||||
$script .= $this->addRemoveTranslation();
|
||||
$script .= $this->addGetCurrentTranslation();
|
||||
|
||||
foreach ($this->behavior->getI18nColumns() as $column) {
|
||||
$script .= $this->addTranslatedColumnGetter($column);
|
||||
$script .= $this->addTranslatedColumnSetter($column);
|
||||
}
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
protected function addSetLocale()
|
||||
{
|
||||
return $this->behavior->renderTemplate('objectSetLocale', array(
|
||||
'objectClassName' => $this->builder->getClassNameFromBuilder($this->builder->getStubObjectBuilder($this->table)),
|
||||
'defaultLocale' => $this->behavior->getDefaultLocale(),
|
||||
'localeColumnName' => $this->behavior->getLocaleColumn()->getPhpName(),
|
||||
));
|
||||
}
|
||||
|
||||
protected function addGetLocale()
|
||||
{
|
||||
return $this->behavior->renderTemplate('objectGetLocale', array(
|
||||
'localeColumnName' => $this->behavior->getLocaleColumn()->getPhpName(),
|
||||
));
|
||||
}
|
||||
|
||||
protected function addSetLocaleAlias($alias)
|
||||
{
|
||||
return $this->behavior->renderTemplate('objectSetLocaleAlias', array(
|
||||
'objectClassName' => $this->builder->getClassNameFromBuilder($this->builder->getStubObjectBuilder($this->table)),
|
||||
'defaultLocale' => $this->behavior->getDefaultLocale(),
|
||||
'alias' => ucfirst($alias),
|
||||
));
|
||||
}
|
||||
|
||||
protected function addGetLocaleAlias($alias)
|
||||
{
|
||||
return $this->behavior->renderTemplate('objectGetLocaleAlias', array(
|
||||
'alias' => ucfirst($alias),
|
||||
));
|
||||
}
|
||||
|
||||
protected function addGetTranslation()
|
||||
{
|
||||
$plural = false;
|
||||
$i18nTable = $this->behavior->getI18nTable();
|
||||
$fk = $this->behavior->getI18nForeignKey();
|
||||
|
||||
return $this->behavior->renderTemplate('objectGetTranslation', array(
|
||||
'i18nTablePhpName' => $this->builder->getClassNameFromBuilder($this->builder->getNewStubObjectBuilder($i18nTable)),
|
||||
'defaultLocale' => $this->behavior->getDefaultLocale(),
|
||||
'i18nListVariable' => $this->builder->getRefFKCollVarName($fk),
|
||||
'localeColumnName' => $this->behavior->getLocaleColumn()->getPhpName(),
|
||||
'i18nQueryName' => $this->builder->getClassNameFromBuilder($this->builder->getNewStubQueryBuilder($i18nTable)),
|
||||
'i18nSetterMethod' => $this->builder->getRefFKPhpNameAffix($fk, $plural),
|
||||
));
|
||||
}
|
||||
|
||||
protected function addRemoveTranslation()
|
||||
{
|
||||
$i18nTable = $this->behavior->getI18nTable();
|
||||
$fk = $this->behavior->getI18nForeignKey();
|
||||
|
||||
return $this->behavior->renderTemplate('objectRemoveTranslation', array(
|
||||
'objectClassName' => $this->builder->getClassNameFromBuilder($this->builder->getStubObjectBuilder($this->table)),
|
||||
'defaultLocale' => $this->behavior->getDefaultLocale(),
|
||||
'i18nQueryName' => $this->builder->getClassNameFromBuilder($this->builder->getNewStubQueryBuilder($i18nTable)),
|
||||
'i18nCollection' => $this->builder->getRefFKCollVarName($fk),
|
||||
'localeColumnName' => $this->behavior->getLocaleColumn()->getPhpName(),
|
||||
));
|
||||
}
|
||||
|
||||
protected function addGetCurrentTranslation()
|
||||
{
|
||||
return $this->behavior->renderTemplate('objectGetCurrentTranslation', array(
|
||||
'i18nTablePhpName' => $this->builder->getClassNameFromBuilder($this->builder->getNewStubObjectBuilder($this->behavior->getI18nTable())),
|
||||
));
|
||||
}
|
||||
|
||||
// FIXME: the connection used by getCurrentTranslation in the generated code
|
||||
// cannot be specified by the user
|
||||
protected function addTranslatedColumnGetter(Column $column)
|
||||
{
|
||||
$objectBuilder = $this->builder->getNewObjectBuilder($this->behavior->getI18nTable());
|
||||
$comment = '';
|
||||
$functionStatement = '';
|
||||
if ($this->isDateType($column->getType())) {
|
||||
$objectBuilder->addTemporalAccessorComment($comment, $column);
|
||||
$objectBuilder->addTemporalAccessorOpen($functionStatement, $column);
|
||||
} else {
|
||||
$objectBuilder->addDefaultAccessorComment($comment, $column);
|
||||
$objectBuilder->addDefaultAccessorOpen($functionStatement, $column);
|
||||
}
|
||||
$comment = preg_replace('/^\t/m', '', $comment);
|
||||
$functionStatement = preg_replace('/^\t/m', '', $functionStatement);
|
||||
preg_match_all('/\$[a-z]+/i', $functionStatement, $params);
|
||||
|
||||
return $this->behavior->renderTemplate('objectTranslatedColumnGetter', array(
|
||||
'comment' => $comment,
|
||||
'functionStatement' => $functionStatement,
|
||||
'columnPhpName' => $column->getPhpName(),
|
||||
'params' => implode(', ', $params[0]),
|
||||
));
|
||||
}
|
||||
|
||||
// FIXME: the connection used by getCurrentTranslation in the generated code
|
||||
// cannot be specified by the user
|
||||
protected function addTranslatedColumnSetter(Column $column)
|
||||
{
|
||||
$i18nTablePhpName = $this->builder->getClassNameFromBuilder($this->builder->getNewStubObjectBuilder($this->behavior->getI18nTable()));
|
||||
$tablePhpName = $this->builder->getObjectClassName();
|
||||
$objectBuilder = $this->builder->getNewObjectBuilder($this->behavior->getI18nTable());
|
||||
$comment = '';
|
||||
$functionStatement = '';
|
||||
if ($this->isDateType($column->getType())) {
|
||||
$objectBuilder->addTemporalMutatorComment($comment, $column);
|
||||
$objectBuilder->addMutatorOpenOpen($functionStatement, $column);
|
||||
} else {
|
||||
$objectBuilder->addMutatorComment($comment, $column);
|
||||
$objectBuilder->addMutatorOpenOpen($functionStatement, $column);
|
||||
}
|
||||
$comment = preg_replace('/^\t/m', '', $comment);
|
||||
$comment = str_replace('@return ' . $i18nTablePhpName, '@return ' . $tablePhpName, $comment);
|
||||
$functionStatement = preg_replace('/^\t/m', '', $functionStatement);
|
||||
preg_match_all('/\$[a-z]+/i', $functionStatement, $params);
|
||||
|
||||
return $this->behavior->renderTemplate('objectTranslatedColumnSetter', array(
|
||||
'comment' => $comment,
|
||||
'functionStatement' => $functionStatement,
|
||||
'columnPhpName' => $column->getPhpName(),
|
||||
'params' => implode(', ', $params[0]),
|
||||
));
|
||||
}
|
||||
|
||||
public function objectFilter(&$script, $builder)
|
||||
{
|
||||
$i18nTable = $this->behavior->getI18nTable();
|
||||
$i18nTablePhpName = $this->builder->getNewStubObjectBuilder($i18nTable)->getUnprefixedClassName();
|
||||
$localeColumnName = $this->behavior->getLocaleColumn()->getPhpName();
|
||||
$pattern = '/public function add' . $i18nTablePhpName . '.*[\r\n]\s*\{/';
|
||||
$addition = "
|
||||
if (\$l && \$locale = \$l->get$localeColumnName()) {
|
||||
\$this->set{$localeColumnName}(\$locale);
|
||||
\$this->currentTranslations[\$locale] = \$l;
|
||||
}";
|
||||
$replacement = "\$0$addition";
|
||||
$script = preg_replace($pattern, $replacement, $script);
|
||||
}
|
||||
|
||||
protected function isDateType($columnType)
|
||||
{
|
||||
return in_array($columnType, array(
|
||||
PropelTypes::DATE,
|
||||
PropelTypes::TIME,
|
||||
PropelTypes::TIMESTAMP
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<?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\Behavior\I18n;
|
||||
|
||||
/**
|
||||
* Allows translation of text columns through transparent one-to-many relationship.
|
||||
* Modifier for the query builder.
|
||||
*
|
||||
* @author François Zaninotto
|
||||
*/
|
||||
class I18nBehaviorQueryBuilderModifier
|
||||
{
|
||||
protected $behavior;
|
||||
|
||||
protected $table;
|
||||
|
||||
protected $builder;
|
||||
|
||||
public function __construct($behavior)
|
||||
{
|
||||
$this->behavior = $behavior;
|
||||
$this->table = $behavior->getTable();
|
||||
}
|
||||
|
||||
public function queryMethods($builder)
|
||||
{
|
||||
$this->builder = $builder;
|
||||
$script = '';
|
||||
$script .= $this->addJoinI18n();
|
||||
$script .= $this->addJoinWithI18n();
|
||||
$script .= $this->addUseI18nQuery();
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
protected function addJoinI18n()
|
||||
{
|
||||
$fk = $this->behavior->getI18nForeignKey();
|
||||
|
||||
return $this->behavior->renderTemplate('queryJoinI18n', array(
|
||||
'queryClass' => $this->builder->getQueryClassName(),
|
||||
'defaultLocale' => $this->behavior->getDefaultLocale(),
|
||||
'i18nRelationName' => $this->builder->getRefFKPhpNameAffix($fk),
|
||||
'localeColumn' => $this->behavior->getLocaleColumn()->getPhpName(),
|
||||
));
|
||||
}
|
||||
|
||||
protected function addJoinWithI18n()
|
||||
{
|
||||
$fk = $this->behavior->getI18nForeignKey();
|
||||
|
||||
return $this->behavior->renderTemplate('queryJoinWithI18n', array(
|
||||
'queryClass' => $this->builder->getQueryClassName(),
|
||||
'defaultLocale' => $this->behavior->getDefaultLocale(),
|
||||
'i18nRelationName' => $this->builder->getRefFKPhpNameAffix($fk),
|
||||
));
|
||||
}
|
||||
|
||||
protected function addUseI18nQuery()
|
||||
{
|
||||
$i18nTable = $this->behavior->getI18nTable();
|
||||
$fk = $this->behavior->getI18nForeignKey();
|
||||
|
||||
return $this->behavior->renderTemplate('queryUseI18nQuery', array(
|
||||
'queryClass' => $this->builder->getClassNameFromBuilder($this->builder->getNewStubQueryBuilder($i18nTable)),
|
||||
'namespacedQueryClass' => $this->builder->getNewStubQueryBuilder($i18nTable)->getFullyQualifiedClassName(),
|
||||
'defaultLocale' => $this->behavior->getDefaultLocale(),
|
||||
'i18nRelationName' => $this->builder->getRefFKPhpNameAffix($fk),
|
||||
'localeColumn' => $this->behavior->getLocaleColumn()->getPhpName(),
|
||||
));
|
||||
}
|
||||
}
|
||||
12
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/templates/objectAttributes.php
vendored
Normal file
12
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/templates/objectAttributes.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
/**
|
||||
* Current locale
|
||||
* @var string
|
||||
*/
|
||||
protected $currentLocale = '<?= $defaultLocale ?>';
|
||||
|
||||
/**
|
||||
* Current translation objects
|
||||
* @var array[<?= $objectClassName ?>]
|
||||
*/
|
||||
protected $currentTranslations;
|
||||
@@ -0,0 +1,2 @@
|
||||
$this->currentLocale = '<?= $defaultLocale ?>';
|
||||
$this->currentTranslations = null;
|
||||
@@ -0,0 +1,12 @@
|
||||
|
||||
/**
|
||||
* Returns the current translation
|
||||
*
|
||||
* @param ConnectionInterface $con an optional connection object
|
||||
*
|
||||
* @return <?= $i18nTablePhpName ?>
|
||||
*/
|
||||
public function getCurrentTranslation(ConnectionInterface $con = null)
|
||||
{
|
||||
return $this->getTranslation($this->getLocale(), $con);
|
||||
}
|
||||
10
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/templates/objectGetLocale.php
vendored
Normal file
10
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/templates/objectGetLocale.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
/**
|
||||
* Gets the locale for translations
|
||||
*
|
||||
* @return string $locale Locale to use for the translation, e.g. 'fr_FR'
|
||||
*/
|
||||
public function get<?= $localeColumnName ?>()
|
||||
{
|
||||
return $this->currentLocale;
|
||||
}
|
||||
11
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/templates/objectGetLocaleAlias.php
vendored
Normal file
11
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/templates/objectGetLocaleAlias.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
/**
|
||||
* Gets the locale for translations.
|
||||
* Alias for getLocale(), for BC purpose.
|
||||
*
|
||||
* @return string $locale Locale to use for the translation, e.g. 'fr_FR'
|
||||
*/
|
||||
public function get<?php echo $alias ?>()
|
||||
{
|
||||
return $this->getLocale();
|
||||
}
|
||||
35
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/templates/objectGetTranslation.php
vendored
Normal file
35
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/templates/objectGetTranslation.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
/**
|
||||
* Returns the current translation for a given locale
|
||||
*
|
||||
* @param string $locale Locale to use for the translation, e.g. 'fr_FR'
|
||||
* @param ConnectionInterface $con an optional connection object
|
||||
*
|
||||
* @return <?php echo $i18nTablePhpName ?>
|
||||
*/
|
||||
public function getTranslation($locale = '<?php echo $defaultLocale ?>', ConnectionInterface $con = null)
|
||||
{
|
||||
if (!isset($this->currentTranslations[$locale])) {
|
||||
if (null !== $this-><?php echo $i18nListVariable ?>) {
|
||||
foreach ($this-><?php echo $i18nListVariable ?> as $translation) {
|
||||
if ($translation->get<?php echo $localeColumnName ?>() == $locale) {
|
||||
$this->currentTranslations[$locale] = $translation;
|
||||
|
||||
return $translation;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($this->isNew()) {
|
||||
$translation = new <?php echo $i18nTablePhpName ?>();
|
||||
$translation->set<?php echo $localeColumnName ?>($locale);
|
||||
} else {
|
||||
$translation = <?php echo $i18nQueryName ?>::create()
|
||||
->filterByPrimaryKey(array($this->getPrimaryKey(), $locale))
|
||||
->findOneOrCreate($con);
|
||||
$this->currentTranslations[$locale] = $translation;
|
||||
}
|
||||
$this->add<?php echo $i18nSetterMethod ?>($translation);
|
||||
}
|
||||
|
||||
return $this->currentTranslations[$locale];
|
||||
}
|
||||
5
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/templates/objectPostDelete.php
vendored
Normal file
5
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/templates/objectPostDelete.php
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
// emulate delete cascade
|
||||
<?php echo $i18nQueryName ?>::create()
|
||||
->filterBy<?php echo $objectClassName ?>($this)
|
||||
->delete($con);
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
/**
|
||||
* Remove the translation for a given locale
|
||||
*
|
||||
* @param string $locale Locale to use for the translation, e.g. 'fr_FR'
|
||||
* @param ConnectionInterface $con an optional connection object
|
||||
*
|
||||
* @return <?php echo $objectClassName ?> The current object (for fluent API support)
|
||||
*/
|
||||
public function removeTranslation($locale = '<?php echo $defaultLocale ?>', ConnectionInterface $con = null)
|
||||
{
|
||||
if (!$this->isNew()) {
|
||||
<?php echo $i18nQueryName ?>::create()
|
||||
->filterByPrimaryKey(array($this->getPrimaryKey(), $locale))
|
||||
->delete($con);
|
||||
}
|
||||
if (isset($this->currentTranslations[$locale])) {
|
||||
unset($this->currentTranslations[$locale]);
|
||||
}
|
||||
foreach ($this-><?php echo $i18nCollection ?> as $key => $translation) {
|
||||
if ($translation->get<?php echo $localeColumnName ?>() == $locale) {
|
||||
unset($this-><?php echo $i18nCollection ?>[$key]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
14
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/templates/objectSetLocale.php
vendored
Normal file
14
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/templates/objectSetLocale.php
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
/**
|
||||
* Sets the locale for translations
|
||||
*
|
||||
* @param string $locale Locale to use for the translation, e.g. 'fr_FR'
|
||||
*
|
||||
* @return <?php echo $objectClassName ?> The current object (for fluent API support)
|
||||
*/
|
||||
public function set<?php echo $localeColumnName ?>($locale = '<?php echo $defaultLocale ?>')
|
||||
{
|
||||
$this->currentLocale = $locale;
|
||||
|
||||
return $this;
|
||||
}
|
||||
13
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/templates/objectSetLocaleAlias.php
vendored
Normal file
13
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/templates/objectSetLocaleAlias.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
/**
|
||||
* Sets the locale for translations.
|
||||
* Alias for setLocale(), for BC purpose.
|
||||
*
|
||||
* @param string $locale Locale to use for the translation, e.g. 'fr_FR'
|
||||
*
|
||||
* @return <?php echo $objectClassName ?> The current object (for fluent API support)
|
||||
*/
|
||||
public function set<?php echo $alias ?>($locale = '<?php echo $defaultLocale ?>')
|
||||
{
|
||||
return $this->setLocale($locale);
|
||||
}
|
||||
17
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/templates/objectSetTranslation.php
vendored
Normal file
17
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/templates/objectSetTranslation.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
/**
|
||||
* Sets the translation for a given locale
|
||||
*
|
||||
* @param <?php echo $i18nTablePhpName ?> $translation The translation object
|
||||
* @param string $locale Locale to use for the translation, e.g. 'fr_FR'
|
||||
*
|
||||
* @return <?php echo $objectClassName ?> The current object (for fluent API support)
|
||||
*/
|
||||
public function setTranslation($translation, $locale = '<?php echo $defaultLocale ?>')
|
||||
{
|
||||
$translation->set<?php echo $localeColumnName ?>($locale);
|
||||
$this->add<?php echo $i18nTablePhpName ?>($translation);
|
||||
$this->currentTranslations[$locale] = $translation;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
<?php echo $comment ?>
|
||||
<?php echo $functionStatement ?>
|
||||
|
||||
return $this->getCurrentTranslation()->get<?php echo $columnPhpName ?>(<?php echo $params ?>);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
<?php echo $comment ?>
|
||||
<?php echo $functionStatement ?>
|
||||
$this->getCurrentTranslation()->set<?php echo $columnPhpName ?>(<?php echo $params ?>);
|
||||
|
||||
return $this;
|
||||
}
|
||||
18
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/templates/queryJoinI18n.php
vendored
Normal file
18
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/templates/queryJoinI18n.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
/**
|
||||
* Adds a JOIN clause to the query using the i18n relation
|
||||
*
|
||||
* @param string $locale Locale to use for the join condition, e.g. 'fr_FR'
|
||||
* @param string $relationAlias optional alias for the relation
|
||||
* @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join'. Defaults to left join.
|
||||
*
|
||||
* @return <?php echo $queryClass ?> The current query, for fluid interface
|
||||
*/
|
||||
public function joinI18n($locale = '<?php echo $defaultLocale ?>', $relationAlias = null, $joinType = Criteria::LEFT_JOIN)
|
||||
{
|
||||
$relationName = $relationAlias ? $relationAlias : '<?php echo $i18nRelationName ?>';
|
||||
|
||||
return $this
|
||||
->join<?php echo $i18nRelationName ?>($relationAlias, $joinType)
|
||||
->addJoinCondition($relationName, $relationName . '.<?php echo $localeColumn ?> = ?', $locale);
|
||||
}
|
||||
19
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/templates/queryJoinWithI18n.php
vendored
Normal file
19
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/templates/queryJoinWithI18n.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
/**
|
||||
* Adds a JOIN clause to the query and hydrates the related I18n object.
|
||||
* Shortcut for $c->joinI18n($locale)->with()
|
||||
*
|
||||
* @param string $locale Locale to use for the join condition, e.g. 'fr_FR'
|
||||
* @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join'. Defaults to left join.
|
||||
*
|
||||
* @return <?php echo $queryClass ?> The current query, for fluid interface
|
||||
*/
|
||||
public function joinWithI18n($locale = '<?php echo $defaultLocale ?>', $joinType = Criteria::LEFT_JOIN)
|
||||
{
|
||||
$this
|
||||
->joinI18n($locale, null, $joinType)
|
||||
->with('<?php echo $i18nRelationName ?>');
|
||||
$this->with['<?php echo $i18nRelationName ?>']->setIsWithOneToMany(false);
|
||||
|
||||
return $this;
|
||||
}
|
||||
18
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/templates/queryUseI18nQuery.php
vendored
Normal file
18
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/templates/queryUseI18nQuery.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
/**
|
||||
* Use the I18n relation query object
|
||||
*
|
||||
* @see useQuery()
|
||||
*
|
||||
* @param string $locale Locale to use for the join condition, e.g. 'fr_FR'
|
||||
* @param string $relationAlias optional alias for the relation
|
||||
* @param string $joinType Accepted values are null, 'left join', 'right join', 'inner join'. Defaults to left join.
|
||||
*
|
||||
* @return <?php echo $queryClass ?> A secondary query class using the current class as primary query
|
||||
*/
|
||||
public function useI18nQuery($locale = '<?php echo $defaultLocale ?>', $relationAlias = null, $joinType = Criteria::LEFT_JOIN)
|
||||
{
|
||||
return $this
|
||||
->joinI18n($locale, $relationAlias, $joinType)
|
||||
->useQuery($relationAlias ? $relationAlias : '<?php echo $i18nRelationName ?>', '<?php echo $namespacedQueryClass ?>');
|
||||
}
|
||||
7
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/templates/staticAttributes.php
vendored
Normal file
7
core/vendor/propel/propel/src/Propel/Generator/Behavior/I18n/templates/staticAttributes.php
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
/**
|
||||
* The default locale to use for translations.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const DEFAULT_LOCALE = '<?= $defaultLocale ?>';
|
||||
104
core/vendor/propel/propel/src/Propel/Generator/Behavior/NestedSet/NestedSetBehavior.php
vendored
Normal file
104
core/vendor/propel/propel/src/Propel/Generator/Behavior/NestedSet/NestedSetBehavior.php
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
<?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\Behavior\NestedSet;
|
||||
|
||||
use Propel\Generator\Model\Behavior;
|
||||
|
||||
/**
|
||||
* Behavior to adds nested set tree structure columns and abilities
|
||||
*
|
||||
* @author François Zaninotto
|
||||
*/
|
||||
class NestedSetBehavior extends Behavior
|
||||
{
|
||||
// default parameters value
|
||||
protected $parameters = array(
|
||||
'left_column' => 'tree_left',
|
||||
'right_column' => 'tree_right',
|
||||
'level_column' => 'tree_level',
|
||||
'use_scope' => 'false',
|
||||
'scope_column' => 'tree_scope',
|
||||
'method_proxies' => 'false'
|
||||
);
|
||||
|
||||
protected $objectBuilderModifier;
|
||||
|
||||
protected $queryBuilderModifier;
|
||||
|
||||
/**
|
||||
* Add the left, right and scope to the current table
|
||||
*/
|
||||
public function modifyTable()
|
||||
{
|
||||
$table = $this->getTable();
|
||||
|
||||
if (!$table->hasColumn($this->getParameter('left_column'))) {
|
||||
$table->addColumn(array(
|
||||
'name' => $this->getParameter('left_column'),
|
||||
'type' => 'INTEGER'
|
||||
));
|
||||
}
|
||||
|
||||
if (!$table->hasColumn($this->getParameter('right_column'))) {
|
||||
$table->addColumn(array(
|
||||
'name' => $this->getParameter('right_column'),
|
||||
'type' => 'INTEGER'
|
||||
));
|
||||
}
|
||||
|
||||
if (!$table->hasColumn($this->getParameter('level_column'))) {
|
||||
$table->addColumn(array(
|
||||
'name' => $this->getParameter('level_column'),
|
||||
'type' => 'INTEGER'
|
||||
));
|
||||
}
|
||||
|
||||
if ('true' === $this->getParameter('use_scope') && !$table->hasColumn($this->getParameter('scope_column'))) {
|
||||
$table->addColumn(array(
|
||||
'name' => $this->getParameter('scope_column'),
|
||||
'type' => 'INTEGER'
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
public function getObjectBuilderModifier()
|
||||
{
|
||||
if (null === $this->objectBuilderModifier) {
|
||||
$this->objectBuilderModifier = new NestedSetBehaviorObjectBuilderModifier($this);
|
||||
}
|
||||
|
||||
return $this->objectBuilderModifier;
|
||||
}
|
||||
|
||||
public function getQueryBuilderModifier()
|
||||
{
|
||||
if (null === $this->queryBuilderModifier) {
|
||||
$this->queryBuilderModifier = new NestedSetBehaviorQueryBuilderModifier($this);
|
||||
}
|
||||
|
||||
return $this->queryBuilderModifier;
|
||||
}
|
||||
|
||||
public function useScope()
|
||||
{
|
||||
return 'true' === $this->getParameter('use_scope');
|
||||
}
|
||||
|
||||
public function getColumnConstant($columnName)
|
||||
{
|
||||
return $this->getColumn($columnName)->getName();
|
||||
}
|
||||
|
||||
public function getColumn($columnName)
|
||||
{
|
||||
return $this->getColumnForParameter($columnName);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,917 @@
|
||||
<?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\Behavior\NestedSet;
|
||||
|
||||
/**
|
||||
* Behavior to adds nested set tree structure columns and abilities
|
||||
*
|
||||
* @author François Zaninotto
|
||||
*/
|
||||
class NestedSetBehaviorQueryBuilderModifier
|
||||
{
|
||||
protected $behavior;
|
||||
|
||||
protected $table;
|
||||
|
||||
protected $builder;
|
||||
|
||||
protected $objectClassName;
|
||||
|
||||
protected $queryClassName;
|
||||
|
||||
protected $tableMapClassName;
|
||||
|
||||
public function __construct($behavior)
|
||||
{
|
||||
$this->behavior = $behavior;
|
||||
$this->table = $behavior->getTable();
|
||||
}
|
||||
|
||||
protected function getParameter($key)
|
||||
{
|
||||
return $this->behavior->getParameter($key);
|
||||
}
|
||||
|
||||
protected function getColumn($name)
|
||||
{
|
||||
return $this->behavior->getColumnForParameter($name);
|
||||
}
|
||||
|
||||
protected function setBuilder($builder)
|
||||
{
|
||||
$this->builder = $builder;
|
||||
$this->objectClassName = $builder->getObjectClassName();
|
||||
$this->queryClassName = $builder->getQueryClassName();
|
||||
$this->tableMapClassName = $builder->getTableMapClassName();
|
||||
}
|
||||
|
||||
public function queryMethods($builder)
|
||||
{
|
||||
$this->setBuilder($builder);
|
||||
$script = '';
|
||||
|
||||
// select filters
|
||||
if ($this->behavior->useScope()) {
|
||||
$this->addTreeRoots($script);
|
||||
$this->addInTree($script);
|
||||
}
|
||||
|
||||
$this->addDescendantsOf($script);
|
||||
$this->addBranchOf($script);
|
||||
$this->addChildrenOf($script);
|
||||
$this->addSiblingsOf($script);
|
||||
$this->addAncestorsOf($script);
|
||||
$this->addRootsOf($script);
|
||||
// select orders
|
||||
$this->addOrderByBranch($script);
|
||||
$this->addOrderByLevel($script);
|
||||
// select termination methods
|
||||
$this->addFindRoot($script);
|
||||
if ($this->behavior->useScope()) {
|
||||
$this->addFindRoots($script);
|
||||
}
|
||||
$this->addFindTree($script);
|
||||
|
||||
if ($this->behavior->useScope()) {
|
||||
$this->addRetrieveRoots($script);
|
||||
}
|
||||
|
||||
$this->addRetrieveRoot($script);
|
||||
$this->addRetrieveTree($script);
|
||||
$this->addIsValid($script);
|
||||
$this->addDeleteTree($script);
|
||||
$this->addShiftRLValues($script);
|
||||
$this->addShiftLevel($script);
|
||||
$this->addUpdateLoadedNodes($script);
|
||||
$this->addMakeRoomForLeaf($script);
|
||||
$this->addFixLevels($script);
|
||||
$this->addSetNegativeScope($script);
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
protected function addTreeRoots(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Filter the query to restrict the result to root objects
|
||||
*
|
||||
* @return {$this->queryClassName} The current query, for fluid interface
|
||||
*/
|
||||
public function treeRoots()
|
||||
{
|
||||
return \$this->addUsingAlias({$this->objectClassName}::LEFT_COL, 1, Criteria::EQUAL);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addInTree(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Returns the objects in a certain tree, from the tree scope
|
||||
*
|
||||
* @param int \$scope Scope to determine which objects node to return
|
||||
*
|
||||
* @return {$this->queryClassName} The current query, for fluid interface
|
||||
*/
|
||||
public function inTree(\$scope = null)
|
||||
{
|
||||
return \$this->addUsingAlias({$this->objectClassName}::SCOPE_COL, \$scope, Criteria::EQUAL);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addDescendantsOf(&$script)
|
||||
{
|
||||
$objectName = '$' . $this->table->getStudlyPhpName();
|
||||
$script .= "
|
||||
/**
|
||||
* Filter the query to restrict the result to descendants of an object
|
||||
*
|
||||
* @param {$this->objectClassName} $objectName The object to use for descendant search
|
||||
*
|
||||
* @return {$this->queryClassName} The current query, for fluid interface
|
||||
*/
|
||||
public function descendantsOf($objectName)
|
||||
{
|
||||
return \$this";
|
||||
if ($this->behavior->useScope()) {
|
||||
$script .= "
|
||||
->inTree({$objectName}->getScopeValue())";
|
||||
}
|
||||
$script .= "
|
||||
->addUsingAlias({$this->objectClassName}::LEFT_COL, {$objectName}->getLeftValue(), Criteria::GREATER_THAN)
|
||||
->addUsingAlias({$this->objectClassName}::LEFT_COL, {$objectName}->getRightValue(), Criteria::LESS_THAN);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addBranchOf(&$script)
|
||||
{
|
||||
$objectName = '$' . $this->table->getStudlyPhpName();
|
||||
$script .= "
|
||||
/**
|
||||
* Filter the query to restrict the result to the branch of an object.
|
||||
* Same as descendantsOf(), except that it includes the object passed as parameter in the result
|
||||
*
|
||||
* @param {$this->objectClassName} $objectName The object to use for branch search
|
||||
*
|
||||
* @return {$this->queryClassName} The current query, for fluid interface
|
||||
*/
|
||||
public function branchOf($objectName)
|
||||
{
|
||||
return \$this";
|
||||
if ($this->behavior->useScope()) {
|
||||
$script .= "
|
||||
->inTree({$objectName}->getScopeValue())";
|
||||
}
|
||||
$script .= "
|
||||
->addUsingAlias({$this->objectClassName}::LEFT_COL, {$objectName}->getLeftValue(), Criteria::GREATER_EQUAL)
|
||||
->addUsingAlias({$this->objectClassName}::LEFT_COL, {$objectName}->getRightValue(), Criteria::LESS_EQUAL);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addChildrenOf(&$script)
|
||||
{
|
||||
$objectName = '$' . $this->table->getStudlyPhpName();
|
||||
$script .= "
|
||||
/**
|
||||
* Filter the query to restrict the result to children of an object
|
||||
*
|
||||
* @param {$this->objectClassName} $objectName The object to use for child search
|
||||
*
|
||||
* @return {$this->queryClassName} The current query, for fluid interface
|
||||
*/
|
||||
public function childrenOf($objectName)
|
||||
{
|
||||
return \$this
|
||||
->descendantsOf($objectName)
|
||||
->addUsingAlias({$this->objectClassName}::LEVEL_COL, {$objectName}->getLevel() + 1, Criteria::EQUAL);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addSiblingsOf(&$script)
|
||||
{
|
||||
$objectName = '$' . $this->table->getStudlyPhpName();
|
||||
$script .= "
|
||||
/**
|
||||
* Filter the query to restrict the result to siblings of an object.
|
||||
* The result does not include the object passed as parameter.
|
||||
*
|
||||
* @param {$this->objectClassName} $objectName The object to use for sibling search
|
||||
* @param ConnectionInterface \$con Connection to use.
|
||||
*
|
||||
* @return {$this->queryClassName} The current query, for fluid interface
|
||||
*/
|
||||
public function siblingsOf($objectName, ConnectionInterface \$con = null)
|
||||
{
|
||||
if ({$objectName}->isRoot()) {
|
||||
return \$this->
|
||||
add({$this->objectClassName}::LEVEL_COL, '1<>1', Criteria::CUSTOM);
|
||||
} else {
|
||||
return \$this
|
||||
->childrenOf({$objectName}->getParent(\$con))
|
||||
->prune($objectName);
|
||||
}
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addAncestorsOf(&$script)
|
||||
{
|
||||
$objectName = '$' . $this->table->getStudlyPhpName();
|
||||
$script .= "
|
||||
/**
|
||||
* Filter the query to restrict the result to ancestors of an object
|
||||
*
|
||||
* @param {$this->objectClassName} $objectName The object to use for ancestors search
|
||||
*
|
||||
* @return {$this->queryClassName} The current query, for fluid interface
|
||||
*/
|
||||
public function ancestorsOf($objectName)
|
||||
{
|
||||
return \$this";
|
||||
if ($this->behavior->useScope()) {
|
||||
$script .= "
|
||||
->inTree({$objectName}->getScopeValue())";
|
||||
}
|
||||
$script .= "
|
||||
->addUsingAlias({$this->objectClassName}::LEFT_COL, {$objectName}->getLeftValue(), Criteria::LESS_THAN)
|
||||
->addUsingAlias({$this->objectClassName}::RIGHT_COL, {$objectName}->getRightValue(), Criteria::GREATER_THAN);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addRootsOf(&$script)
|
||||
{
|
||||
$objectName = '$' . $this->table->getStudlyPhpName();
|
||||
$script .= "
|
||||
/**
|
||||
* Filter the query to restrict the result to roots of an object.
|
||||
* Same as ancestorsOf(), except that it includes the object passed as parameter in the result
|
||||
*
|
||||
* @param {$this->objectClassName} $objectName The object to use for roots search
|
||||
*
|
||||
* @return {$this->queryClassName} The current query, for fluid interface
|
||||
*/
|
||||
public function rootsOf($objectName)
|
||||
{
|
||||
return \$this";
|
||||
if ($this->behavior->useScope()) {
|
||||
$script .= "
|
||||
->inTree({$objectName}->getScopeValue())";
|
||||
}
|
||||
$script .= "
|
||||
->addUsingAlias({$this->objectClassName}::LEFT_COL, {$objectName}->getLeftValue(), Criteria::LESS_EQUAL)
|
||||
->addUsingAlias({$this->objectClassName}::RIGHT_COL, {$objectName}->getRightValue(), Criteria::GREATER_EQUAL);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addOrderByBranch(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Order the result by branch, i.e. natural tree order
|
||||
*
|
||||
* @param bool \$reverse if true, reverses the order
|
||||
*
|
||||
* @return {$this->queryClassName} The current query, for fluid interface
|
||||
*/
|
||||
public function orderByBranch(\$reverse = false)
|
||||
{
|
||||
if (\$reverse) {
|
||||
return \$this
|
||||
->addDescendingOrderByColumn({$this->objectClassName}::LEFT_COL);
|
||||
} else {
|
||||
return \$this
|
||||
->addAscendingOrderByColumn({$this->objectClassName}::LEFT_COL);
|
||||
}
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addOrderByLevel(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Order the result by level, the closer to the root first
|
||||
*
|
||||
* @param bool \$reverse if true, reverses the order
|
||||
*
|
||||
* @return {$this->queryClassName} The current query, for fluid interface
|
||||
*/
|
||||
public function orderByLevel(\$reverse = false)
|
||||
{
|
||||
if (\$reverse) {
|
||||
return \$this
|
||||
->addAscendingOrderByColumn({$this->objectClassName}::RIGHT_COL);
|
||||
} else {
|
||||
return \$this
|
||||
->addDescendingOrderByColumn({$this->objectClassName}::RIGHT_COL);
|
||||
}
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addFindRoot(&$script)
|
||||
{
|
||||
$useScope = $this->behavior->useScope();
|
||||
$script .= "
|
||||
/**
|
||||
* Returns " . ($useScope ? 'a' : 'the') ." root node for the tree
|
||||
*";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
* @param int \$scope Scope to determine which root node to return";
|
||||
}
|
||||
|
||||
$script .= "
|
||||
* @param ConnectionInterface \$con Connection to use.
|
||||
*
|
||||
* @return {$this->objectClassName} The tree root object
|
||||
*/
|
||||
public function findRoot(" . ($useScope ? "\$scope = null, " : "") . "\$con = null)
|
||||
{
|
||||
return \$this
|
||||
->addUsingAlias({$this->objectClassName}::LEFT_COL, 1, Criteria::EQUAL)";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
->inTree(\$scope)";
|
||||
}
|
||||
$script .= "
|
||||
->findOne(\$con);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addFindRoots(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Returns the root objects for all trees.
|
||||
*
|
||||
* @param ConnectionInterface \$con Connection to use.
|
||||
*
|
||||
* @return mixed the list of results, formatted by the current formatter
|
||||
*/
|
||||
public function findRoots(\$con = null)
|
||||
{
|
||||
return \$this
|
||||
->treeRoots()
|
||||
->find(\$con);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addFindTree(&$script)
|
||||
{
|
||||
$useScope = $this->behavior->useScope();
|
||||
$script .= "
|
||||
/**
|
||||
* Returns " . ($useScope ? 'a' : 'the') ." tree of objects
|
||||
*";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
* @param int \$scope Scope to determine which tree node to return";
|
||||
}
|
||||
|
||||
$script .= "
|
||||
* @param ConnectionInterface \$con Connection to use.
|
||||
*
|
||||
* @return mixed the list of results, formatted by the current formatter
|
||||
*/
|
||||
public function findTree(" . ($useScope ? "\$scope = null, " : "") . "\$con = null)
|
||||
{
|
||||
return \$this";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
->inTree(\$scope)";
|
||||
}
|
||||
$script .= "
|
||||
->orderByBranch()
|
||||
->find(\$con);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addRetrieveRoots(&$script)
|
||||
{
|
||||
$queryClassName = $this->queryClassName;
|
||||
$objectClassName = $this->objectClassName;
|
||||
$tableMapClassName = $this->builder->getTableMapClass();
|
||||
|
||||
$script .= "
|
||||
/**
|
||||
* Returns the root nodes for the tree
|
||||
*
|
||||
* @param ConnectionInterface \$con Connection to use.
|
||||
* @return {$this->objectClassName} Propel object for root node
|
||||
*/
|
||||
static public function retrieveRoots(Criteria \$criteria = null, ConnectionInterface \$con = null)
|
||||
{
|
||||
if (null === \$criteria) {
|
||||
\$criteria = new Criteria($tableMapClassName::DATABASE_NAME);
|
||||
}
|
||||
\$criteria->add($objectClassName::LEFT_COL, 1, Criteria::EQUAL);
|
||||
|
||||
return $queryClassName::create(null, \$criteria)->find(\$con);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addRetrieveRoot(&$script)
|
||||
{
|
||||
$queryClassName = $this->queryClassName;
|
||||
$objectClassName = $this->objectClassName;
|
||||
$useScope = $this->behavior->useScope();
|
||||
$tableMapClassName = $this->builder->getTableMapClass();
|
||||
|
||||
$script .= "
|
||||
/**
|
||||
* Returns the root node for a given scope
|
||||
*";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
* @param int \$scope Scope to determine which root node to return";
|
||||
}
|
||||
$script .= "
|
||||
* @param ConnectionInterface \$con Connection to use.
|
||||
* @return {$this->objectClassName} Propel object for root node
|
||||
*/
|
||||
static public function retrieveRoot(" . ($useScope ? "\$scope = null, " : "") . "ConnectionInterface \$con = null)
|
||||
{
|
||||
\$c = new Criteria($tableMapClassName::DATABASE_NAME);
|
||||
\$c->add($objectClassName::LEFT_COL, 1, Criteria::EQUAL);";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
\$c->add($objectClassName::SCOPE_COL, \$scope, Criteria::EQUAL);";
|
||||
}
|
||||
$script .= "
|
||||
|
||||
return $queryClassName::create(null, \$c)->findOne(\$con);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addRetrieveTree(&$script)
|
||||
{
|
||||
$queryClassName = $this->queryClassName;
|
||||
$objectClassName = $this->objectClassName;
|
||||
$useScope = $this->behavior->useScope();
|
||||
$tableMapClassName = $this->builder->getTableMapClass();
|
||||
|
||||
$script .= "
|
||||
/**
|
||||
* Returns the whole tree node for a given scope
|
||||
*";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
* @param int \$scope Scope to determine which root node to return";
|
||||
}
|
||||
$script .= "
|
||||
* @param Criteria \$criteria Optional Criteria to filter the query
|
||||
* @param ConnectionInterface \$con Connection to use.
|
||||
* @return {$this->objectClassName} Propel object for root node
|
||||
*/
|
||||
static public function retrieveTree(" . ($useScope ? "\$scope = null, " : "") . "Criteria \$criteria = null, ConnectionInterface \$con = null)
|
||||
{
|
||||
if (null === \$criteria) {
|
||||
\$criteria = new Criteria($tableMapClassName::DATABASE_NAME);
|
||||
}
|
||||
\$criteria->addAscendingOrderByColumn($objectClassName::LEFT_COL);";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
\$criteria->add($objectClassName::SCOPE_COL, \$scope, Criteria::EQUAL);";
|
||||
}
|
||||
$script .= "
|
||||
|
||||
return $queryClassName::create(null, \$criteria)->find(\$con);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addIsValid(&$script)
|
||||
{
|
||||
$objectClassName = $this->objectClassName;
|
||||
|
||||
$script .= "
|
||||
/**
|
||||
* Tests if node is valid
|
||||
*
|
||||
* @param $objectClassName \$node Propel object for src node
|
||||
* @return bool
|
||||
*/
|
||||
static public function isValid($objectClassName \$node = null)
|
||||
{
|
||||
if (is_object(\$node) && \$node->getRightValue() > \$node->getLeftValue()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addDeleteTree(&$script)
|
||||
{
|
||||
$objectClassName = $this->objectClassName;
|
||||
$useScope = $this->behavior->useScope();
|
||||
$tableMapClassName = $this->builder->getTableMapClass();
|
||||
|
||||
$script .= "
|
||||
/**
|
||||
* Delete an entire tree
|
||||
* ";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
* @param int \$scope Scope to determine which tree to delete";
|
||||
}
|
||||
$script .= "
|
||||
* @param ConnectionInterface \$con Connection to use.
|
||||
*
|
||||
* @return int The number of deleted nodes
|
||||
*/
|
||||
static public function deleteTree(" . ($useScope ? "\$scope = null, " : "") . "ConnectionInterface \$con = null)
|
||||
{";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
\$c = new Criteria($tableMapClassName::DATABASE_NAME);
|
||||
\$c->add($objectClassName::SCOPE_COL, \$scope, Criteria::EQUAL);
|
||||
|
||||
return $tableMapClassName::doDelete(\$c, \$con);";
|
||||
} else {
|
||||
$script .= "
|
||||
|
||||
return $tableMapClassName::doDeleteAll(\$con);";
|
||||
}
|
||||
$script .= "
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addShiftRLValues(&$script)
|
||||
{
|
||||
$objectClassName = $this->objectClassName;
|
||||
$useScope = $this->behavior->useScope();
|
||||
$tableMapClassName = $this->builder->getTableMapClass();
|
||||
|
||||
$this->builder->declareClass('Propel\\Runtime\Map\\TableMap');
|
||||
|
||||
$script .= "
|
||||
/**
|
||||
* Adds \$delta to all L and R values that are >= \$first and <= \$last.
|
||||
* '\$delta' can also be negative.
|
||||
*
|
||||
* @param int \$delta Value to be shifted by, can be negative
|
||||
* @param int \$first First node to be shifted
|
||||
* @param int \$last Last node to be shifted (optional)";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
* @param int \$scope Scope to use for the shift";
|
||||
}
|
||||
$script .= "
|
||||
* @param ConnectionInterface \$con Connection to use.
|
||||
*/
|
||||
static public function shiftRLValues(\$delta, \$first, \$last = null" . ($useScope ? ", \$scope = null" : ""). ", ConnectionInterface \$con = null)
|
||||
{
|
||||
if (\$con === null) {
|
||||
\$con = Propel::getServiceContainer()->getWriteConnection($tableMapClassName::DATABASE_NAME);
|
||||
}
|
||||
|
||||
// Shift left column values
|
||||
\$whereCriteria = new Criteria($tableMapClassName::DATABASE_NAME);
|
||||
\$criterion = \$whereCriteria->getNewCriterion($objectClassName::LEFT_COL, \$first, Criteria::GREATER_EQUAL);
|
||||
if (null !== \$last) {
|
||||
\$criterion->addAnd(\$whereCriteria->getNewCriterion($objectClassName::LEFT_COL, \$last, Criteria::LESS_EQUAL));
|
||||
}
|
||||
\$whereCriteria->add(\$criterion);";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
\$whereCriteria->add($objectClassName::SCOPE_COL, \$scope, Criteria::EQUAL);";
|
||||
}
|
||||
$script .= "
|
||||
|
||||
\$valuesCriteria = new Criteria($tableMapClassName::DATABASE_NAME);
|
||||
\$valuesCriteria->add($objectClassName::LEFT_COL, array('raw' => $objectClassName::LEFT_COL . ' + ?', 'value' => \$delta), Criteria::CUSTOM_EQUAL);
|
||||
|
||||
\$whereCriteria->doUpdate(\$valuesCriteria, \$con);
|
||||
|
||||
// Shift right column values
|
||||
\$whereCriteria = new Criteria($tableMapClassName::DATABASE_NAME);
|
||||
\$criterion = \$whereCriteria->getNewCriterion($objectClassName::RIGHT_COL, \$first, Criteria::GREATER_EQUAL);
|
||||
if (null !== \$last) {
|
||||
\$criterion->addAnd(\$whereCriteria->getNewCriterion($objectClassName::RIGHT_COL, \$last, Criteria::LESS_EQUAL));
|
||||
}
|
||||
\$whereCriteria->add(\$criterion);";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
\$whereCriteria->add($objectClassName::SCOPE_COL, \$scope, Criteria::EQUAL);";
|
||||
}
|
||||
$script .= "
|
||||
|
||||
\$valuesCriteria = new Criteria($tableMapClassName::DATABASE_NAME);
|
||||
\$valuesCriteria->add($objectClassName::RIGHT_COL, array('raw' => $objectClassName::RIGHT_COL . ' + ?', 'value' => \$delta), Criteria::CUSTOM_EQUAL);
|
||||
|
||||
\$whereCriteria->doUpdate(\$valuesCriteria, \$con);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addShiftLevel(&$script)
|
||||
{
|
||||
$objectClassName = $this->objectClassName;
|
||||
$useScope = $this->behavior->useScope();
|
||||
$tableMapClassName = $this->builder->getTableMapClass();
|
||||
|
||||
$this->builder->declareClass('Propel\\Runtime\Map\\TableMap');
|
||||
|
||||
$script .= "
|
||||
/**
|
||||
* Adds \$delta to level for nodes having left value >= \$first and right value <= \$last.
|
||||
* '\$delta' can also be negative.
|
||||
*
|
||||
* @param int \$delta Value to be shifted by, can be negative
|
||||
* @param int \$first First node to be shifted
|
||||
* @param int \$last Last node to be shifted";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
* @param int \$scope Scope to use for the shift";
|
||||
}
|
||||
$script .= "
|
||||
* @param ConnectionInterface \$con Connection to use.
|
||||
*/
|
||||
static public function shiftLevel(\$delta, \$first, \$last" . ($useScope ? ", \$scope = null" : ""). ", ConnectionInterface \$con = null)
|
||||
{
|
||||
if (\$con === null) {
|
||||
\$con = Propel::getServiceContainer()->getWriteConnection($tableMapClassName::DATABASE_NAME);
|
||||
}
|
||||
|
||||
\$whereCriteria = new Criteria($tableMapClassName::DATABASE_NAME);
|
||||
\$whereCriteria->add($objectClassName::LEFT_COL, \$first, Criteria::GREATER_EQUAL);
|
||||
\$whereCriteria->add($objectClassName::RIGHT_COL, \$last, Criteria::LESS_EQUAL);";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
\$whereCriteria->add($objectClassName::SCOPE_COL, \$scope, Criteria::EQUAL);";
|
||||
}
|
||||
$script .= "
|
||||
|
||||
\$valuesCriteria = new Criteria($tableMapClassName::DATABASE_NAME);
|
||||
\$valuesCriteria->add($objectClassName::LEVEL_COL, array('raw' => $objectClassName::LEVEL_COL . ' + ?', 'value' => \$delta), Criteria::CUSTOM_EQUAL);
|
||||
|
||||
\$whereCriteria->doUpdate(\$valuesCriteria, \$con);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addUpdateLoadedNodes(&$script)
|
||||
{
|
||||
$queryClassName = $this->queryClassName;
|
||||
$objectClassName = $this->objectClassName;
|
||||
$tableMapClassName = $this->tableMapClassName;
|
||||
|
||||
$script .= "
|
||||
/**
|
||||
* Reload all already loaded nodes to sync them with updated db
|
||||
*
|
||||
* @param $objectClassName \$prune Object to prune from the update
|
||||
* @param ConnectionInterface \$con Connection to use.
|
||||
*/
|
||||
static public function updateLoadedNodes(\$prune = null, ConnectionInterface \$con = null)
|
||||
{
|
||||
if (Propel::isInstancePoolingEnabled()) {
|
||||
\$keys = array();
|
||||
foreach ($tableMapClassName::\$instances as \$obj) {
|
||||
if (!\$prune || !\$prune->equals(\$obj)) {
|
||||
\$keys[] = \$obj->getPrimaryKey();
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty(\$keys)) {
|
||||
// We don't need to alter the object instance pool; we're just modifying these ones
|
||||
// already in the pool.
|
||||
\$criteria = new Criteria($tableMapClassName::DATABASE_NAME);";
|
||||
if (1 === count($this->table->getPrimaryKey())) {
|
||||
$pkey = $this->table->getPrimaryKey();
|
||||
$col = array_shift($pkey);
|
||||
$script .= "
|
||||
\$criteria->add(".$this->builder->getColumnConstant($col).", \$keys, Criteria::IN);";
|
||||
} else {
|
||||
$fields = array();
|
||||
foreach ($this->table->getPrimaryKey() as $k => $col) {
|
||||
$fields[] = $this->builder->getColumnConstant($col);
|
||||
};
|
||||
$script .= "
|
||||
|
||||
// Loop on each instances in pool
|
||||
foreach (\$keys as \$values) {
|
||||
// Create initial Criterion
|
||||
\$cton = \$criteria->getNewCriterion(" . $fields[0] . ", \$values[0]);";
|
||||
unset($fields[0]);
|
||||
foreach ($fields as $k => $col) {
|
||||
$script .= "
|
||||
|
||||
// Create next criterion
|
||||
\$nextcton = \$criteria->getNewCriterion(" . $col . ", \$values[$k]);
|
||||
// And merge it with the first
|
||||
\$cton->addAnd(\$nextcton);";
|
||||
}
|
||||
$script .= "
|
||||
|
||||
// Add final Criterion to Criteria
|
||||
\$criteria->addOr(\$cton);
|
||||
}";
|
||||
}
|
||||
|
||||
$script .= "
|
||||
\$dataFetcher = $queryClassName::create(null, \$criteria)->setFormatter(ModelCriteria::FORMAT_STATEMENT)->find(\$con);
|
||||
while (\$row = \$dataFetcher->fetch()) {
|
||||
\$key = $tableMapClassName::getPrimaryKeyHashFromRow(\$row, 0);
|
||||
if (null !== (\$object = $tableMapClassName::getInstanceFromPool(\$key))) {";
|
||||
$n = 0;
|
||||
foreach ($this->table->getColumns() as $col) {
|
||||
if ($col->isLazyLoad()) {
|
||||
continue;
|
||||
}
|
||||
if ($col->getPhpName() == $this->getColumnPhpName('left_column')) {
|
||||
$script .= "
|
||||
\$object->setLeftValue(\$row[$n]);";
|
||||
} elseif ($col->getPhpName() == $this->getColumnPhpName('right_column')) {
|
||||
$script .= "
|
||||
\$object->setRightValue(\$row[$n]);";
|
||||
} elseif ($this->getParameter('use_scope') == 'true' && $col->getPhpName() == $this->getColumnPhpName('scope_column')) {
|
||||
$script .= "
|
||||
\$object->setScopeValue(\$row[$n]);";
|
||||
} elseif ($col->getPhpName() == $this->getColumnPhpName('level_column')) {
|
||||
$script .= "
|
||||
\$object->setLevel(\$row[$n]);
|
||||
\$object->clearNestedSetChildren();";
|
||||
}
|
||||
$n++;
|
||||
}
|
||||
$script .= "
|
||||
}
|
||||
}
|
||||
\$dataFetcher->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addMakeRoomForLeaf(&$script)
|
||||
{
|
||||
$queryClassName = $this->queryClassName;
|
||||
$useScope = $this->behavior->useScope();
|
||||
|
||||
$script .= "
|
||||
/**
|
||||
* Update the tree to allow insertion of a leaf at the specified position
|
||||
*
|
||||
* @param int \$left left column value";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
* @param integer \$scope scope column value";
|
||||
}
|
||||
$script .= "
|
||||
* @param mixed \$prune Object to prune from the shift
|
||||
* @param ConnectionInterface \$con Connection to use.
|
||||
*/
|
||||
static public function makeRoomForLeaf(\$left" . ($useScope ? ", \$scope" : ""). ", \$prune = null, ConnectionInterface \$con = null)
|
||||
{
|
||||
// Update database nodes
|
||||
$queryClassName::shiftRLValues(2, \$left, null" . ($useScope ? ", \$scope" : "") . ", \$con);
|
||||
|
||||
// Update all loaded nodes
|
||||
$queryClassName::updateLoadedNodes(\$prune, \$con);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addFixLevels(&$script)
|
||||
{
|
||||
$objectClassName = $this->objectClassName;
|
||||
$queryClassName = $this->queryClassName;
|
||||
$tableMapClassName = $this->tableMapClassName;
|
||||
$useScope = $this->behavior->useScope();
|
||||
|
||||
$script .= "
|
||||
/**
|
||||
* Update the tree to allow insertion of a leaf at the specified position
|
||||
*";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
* @param integer \$scope scope column value";
|
||||
}
|
||||
$script .= "
|
||||
* @param ConnectionInterface \$con Connection to use.
|
||||
*/
|
||||
static public function fixLevels(" . ($useScope ? "\$scope, " : ""). "ConnectionInterface \$con = null)
|
||||
{
|
||||
\$c = new Criteria();";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
\$c->add($objectClassName::SCOPE_COL, \$scope, Criteria::EQUAL);";
|
||||
}
|
||||
$script .= "
|
||||
\$c->addAscendingOrderByColumn($objectClassName::LEFT_COL);
|
||||
\$dataFetcher = $queryClassName::create(null, \$c)->setFormatter(ModelCriteria::FORMAT_STATEMENT)->find(\$con);
|
||||
";
|
||||
if (!$this->table->getChildrenColumn()) {
|
||||
$script .= "
|
||||
// set the class once to avoid overhead in the loop
|
||||
\$cls = $tableMapClassName::getOMClass(false);";
|
||||
}
|
||||
|
||||
$script .= "
|
||||
\$level = null;
|
||||
// iterate over the statement
|
||||
while (\$row = \$dataFetcher->fetch()) {
|
||||
|
||||
// hydrate object
|
||||
\$key = $tableMapClassName::getPrimaryKeyHashFromRow(\$row, 0);
|
||||
if (null === (\$obj = $tableMapClassName::getInstanceFromPool(\$key))) {";
|
||||
if ($this->table->getChildrenColumn()) {
|
||||
$script .= "
|
||||
// class must be set each time from the record row
|
||||
\$cls = $tableMapClassName::getOMClass(\$row, 0);
|
||||
\$cls = substr('.'.\$cls, strrpos('.'.\$cls, '.') + 1);
|
||||
" . $this->builder->buildObjectInstanceCreationCode('$obj', '$cls') . "
|
||||
\$obj->hydrate(\$row);
|
||||
$tableMapClassName::addInstanceToPool(\$obj, \$key);";
|
||||
} else {
|
||||
$script .= "
|
||||
" . $this->builder->buildObjectInstanceCreationCode('$obj', '$cls') . "
|
||||
\$obj->hydrate(\$row);
|
||||
$tableMapClassName::addInstanceToPool(\$obj, \$key);";
|
||||
}
|
||||
$script .= "
|
||||
}
|
||||
|
||||
// compute level
|
||||
// Algorithm shamelessly stolen from sfPropelActAsNestedSetBehaviorPlugin
|
||||
// Probably authored by Tristan Rivoallan
|
||||
if (\$level === null) {
|
||||
\$level = 0;
|
||||
\$i = 0;
|
||||
\$prev = array(\$obj->getRightValue());
|
||||
} else {
|
||||
while (\$obj->getRightValue() > \$prev[\$i]) {
|
||||
\$i--;
|
||||
}
|
||||
\$level = ++\$i;
|
||||
\$prev[\$i] = \$obj->getRightValue();
|
||||
}
|
||||
|
||||
// update level in node if necessary
|
||||
if (\$obj->getLevel() !== \$level) {
|
||||
\$obj->setLevel(\$level);
|
||||
\$obj->save(\$con);
|
||||
}
|
||||
}
|
||||
\$dataFetcher->close();
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addSetNegativeScope(&$script)
|
||||
{
|
||||
$objectClassName = $this->objectClassName;
|
||||
$tableMapClassName = $this->tableMapClassName;
|
||||
$script .= "
|
||||
/**
|
||||
* Updates all scope values for items that has negative left (<=0) values.
|
||||
*
|
||||
* @param mixed \$scope
|
||||
* @param ConnectionInterface \$con Connection to use.
|
||||
*/
|
||||
public static function setNegativeScope(\$scope, ConnectionInterface \$con = null)
|
||||
{
|
||||
//adjust scope value to \$scope
|
||||
\$whereCriteria = new Criteria($tableMapClassName::DATABASE_NAME);
|
||||
\$whereCriteria->add($objectClassName::LEFT_COL, 0, Criteria::LESS_EQUAL);
|
||||
|
||||
\$valuesCriteria = new Criteria($tableMapClassName::DATABASE_NAME);
|
||||
\$valuesCriteria->add($objectClassName::SCOPE_COL, \$scope, Criteria::EQUAL);
|
||||
|
||||
\$whereCriteria->doUpdate(\$valuesCriteria, \$con);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function getColumnPhpName($columnName)
|
||||
{
|
||||
return $this->behavior->getColumnForParameter($columnName)->getPhpName();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
/**
|
||||
* Returns a pre-order iterator for this node and its children.
|
||||
*
|
||||
* @return RecursiveIterator
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
return new NestedSetRecursiveIterator($this);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
|
||||
/**
|
||||
* Inserts the current node as last child of given $parent node
|
||||
* The modifications in the current object and the tree
|
||||
* are not persisted until the current object is saved.
|
||||
*
|
||||
* @param <?= $objectClassName ?> $parent Propel object for parent node
|
||||
* @return <?= $objectClassName ?> The current Propel object
|
||||
*/
|
||||
public function insertAsLastChildOf($parent)
|
||||
{
|
||||
if ($this->isInTree()) {
|
||||
throw new PropelException(
|
||||
'A <?= $objectClassName ?> object must not already be in the tree to be inserted. Use the moveToLastChildOf() instead.'
|
||||
);
|
||||
}
|
||||
|
||||
$left = $parent->getRightValue();
|
||||
// Update node properties
|
||||
$this->setLeftValue($left);
|
||||
$this->setRightValue($left + 1);
|
||||
$this->setLevel($parent->getLevel() + 1);
|
||||
|
||||
<?php if ($useScope) : ?>
|
||||
$scope = $parent->getScopeValue();
|
||||
$this->setScopeValue($scope);
|
||||
|
||||
<?php endif; ?>
|
||||
// update the children collection of the parent
|
||||
$parent->addNestedSetChild($this);
|
||||
|
||||
// Keep the tree modification query for the save() transaction
|
||||
$this->nestedSetQueries []= array(
|
||||
'callable' => array('<?= $queryClassName ?>', 'makeRoomForLeaf'),
|
||||
'arguments' => array($left<?= $useScope ? ', $scope' : '' ?>, $this->isNew() ? null : $this)
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
12
core/vendor/propel/propel/src/Propel/Generator/Behavior/NestedSet/templates/objectSetLeft.php
vendored
Normal file
12
core/vendor/propel/propel/src/Propel/Generator/Behavior/NestedSet/templates/objectSetLeft.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
/**
|
||||
* Proxy setter method for the left value of the nested set model.
|
||||
* It provides a generic way to set the value, whatever the actual column name is.
|
||||
*
|
||||
* @param int $v The nested set left value
|
||||
* @return <?= $objectClassName ?> The current object (for fluent API support)
|
||||
*/
|
||||
public function setLeftValue($v)
|
||||
{
|
||||
return $this->set<?= $leftColumn ?>($v);
|
||||
}
|
||||
269
core/vendor/propel/propel/src/Propel/Generator/Behavior/QueryCache/QueryCacheBehavior.php
vendored
Normal file
269
core/vendor/propel/propel/src/Propel/Generator/Behavior/QueryCache/QueryCacheBehavior.php
vendored
Normal file
@@ -0,0 +1,269 @@
|
||||
<?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\Behavior\QueryCache;
|
||||
|
||||
use Propel\Generator\Model\Behavior;
|
||||
|
||||
/**
|
||||
* Speeds up queries on a model by caching the query
|
||||
*
|
||||
* @author François Zaninotto
|
||||
*/
|
||||
class QueryCacheBehavior extends Behavior
|
||||
{
|
||||
// default parameters value
|
||||
protected $parameters = array(
|
||||
'backend' => 'apc',
|
||||
'lifetime' => 3600,
|
||||
);
|
||||
|
||||
private $tableClassName;
|
||||
|
||||
public function queryAttributes($builder)
|
||||
{
|
||||
$script = "protected \$queryKey = '';
|
||||
";
|
||||
switch ($this->getParameter('backend')) {
|
||||
case 'backend':
|
||||
$script .= "protected static \$cacheBackend = array();
|
||||
";
|
||||
break;
|
||||
case 'apc':
|
||||
break;
|
||||
case 'custom':
|
||||
default:
|
||||
$script .= "protected static \$cacheBackend;
|
||||
";
|
||||
break;
|
||||
}
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
public function queryMethods($builder)
|
||||
{
|
||||
$builder->declareClasses('\Propel\Runtime\Propel');
|
||||
$this->tableClassName = $builder->getTableMapClassName();
|
||||
$script = '';
|
||||
$this->addSetQueryKey($script);
|
||||
$this->addGetQueryKey($script);
|
||||
$this->addCacheContains($script);
|
||||
$this->addCacheFetch($script);
|
||||
$this->addCacheStore($script);
|
||||
$this->addDoSelect($script);
|
||||
$this->addDoCount($script);
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
protected function addSetQueryKey(&$script)
|
||||
{
|
||||
$script .= "
|
||||
public function setQueryKey(\$key)
|
||||
{
|
||||
\$this->queryKey = \$key;
|
||||
|
||||
return \$this;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addGetQueryKey(&$script)
|
||||
{
|
||||
$script .= "
|
||||
public function getQueryKey()
|
||||
{
|
||||
return \$this->queryKey;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addCacheContains(&$script)
|
||||
{
|
||||
$script .= "
|
||||
public function cacheContains(\$key)
|
||||
{";
|
||||
switch ($this->getParameter('backend')) {
|
||||
case 'apc':
|
||||
$script .= "
|
||||
|
||||
return apc_fetch(\$key);";
|
||||
break;
|
||||
case 'array':
|
||||
$script .= "
|
||||
|
||||
return isset(self::\$cacheBackend[\$key]);";
|
||||
break;
|
||||
case 'custom':
|
||||
default:
|
||||
$script .= "
|
||||
throw new PropelException('You must override the cacheContains(), cacheStore(), and cacheFetch() methods to enable query cache');";
|
||||
break;
|
||||
|
||||
}
|
||||
$script .= "
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addCacheStore(&$script)
|
||||
{
|
||||
$script .= "
|
||||
public function cacheStore(\$key, \$value, \$lifetime = " .$this->getParameter('lifetime') . ")
|
||||
{";
|
||||
switch ($this->getParameter('backend')) {
|
||||
case 'apc':
|
||||
$script .= "
|
||||
apc_store(\$key, \$value, \$lifetime);";
|
||||
break;
|
||||
case 'array':
|
||||
$script .= "
|
||||
self::\$cacheBackend[\$key] = \$value;";
|
||||
break;
|
||||
case 'custom':
|
||||
default:
|
||||
$script .= "
|
||||
throw new PropelException('You must override the cacheContains(), cacheStore(), and cacheFetch() methods to enable query cache');";
|
||||
break;
|
||||
}
|
||||
$script .= "
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addCacheFetch(&$script)
|
||||
{
|
||||
$script .= "
|
||||
public function cacheFetch(\$key)
|
||||
{";
|
||||
switch ($this->getParameter('backend')) {
|
||||
case 'apc':
|
||||
$script .= "
|
||||
|
||||
return apc_fetch(\$key);";
|
||||
break;
|
||||
case 'array':
|
||||
$script .= "
|
||||
|
||||
return isset(self::\$cacheBackend[\$key]) ? self::\$cacheBackend[\$key] : null;";
|
||||
break;
|
||||
case 'custom':
|
||||
default:
|
||||
$script .= "
|
||||
throw new PropelException('You must override the cacheContains(), cacheStore(), and cacheFetch() methods to enable query cache');";
|
||||
break;
|
||||
}
|
||||
$script .= "
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addDoSelect(&$script)
|
||||
{
|
||||
$script .= "
|
||||
public function doSelect(\$con = null)
|
||||
{
|
||||
// check that the columns of the main class are already added (if this is the primary ModelCriteria)
|
||||
if (!\$this->hasSelectClause() && !\$this->getPrimaryCriteria()) {
|
||||
\$this->addSelfSelectColumns();
|
||||
}
|
||||
\$this->configureSelectColumns();
|
||||
|
||||
\$dbMap = Propel::getServiceContainer()->getDatabaseMap(" . $this->tableClassName ."::DATABASE_NAME);
|
||||
\$db = Propel::getServiceContainer()->getAdapter(" . $this->tableClassName ."::DATABASE_NAME);
|
||||
|
||||
\$key = \$this->getQueryKey();
|
||||
if (\$key && \$this->cacheContains(\$key)) {
|
||||
\$params = \$this->getParams();
|
||||
\$sql = \$this->cacheFetch(\$key);
|
||||
} else {
|
||||
\$params = array();
|
||||
\$sql = \$this->createSelectSql(\$params);
|
||||
if (\$key) {
|
||||
\$this->cacheStore(\$key, \$sql);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
\$stmt = \$con->prepare(\$sql);
|
||||
\$db->bindValues(\$stmt, \$params, \$dbMap);
|
||||
\$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);
|
||||
}
|
||||
|
||||
return \$con->getDataFetcher(\$stmt);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addDoCount(&$script)
|
||||
{
|
||||
$script .= "
|
||||
public function doCount(\$con = null)
|
||||
{
|
||||
\$dbMap = Propel::getServiceContainer()->getDatabaseMap(\$this->getDbName());
|
||||
\$db = Propel::getServiceContainer()->getAdapter(\$this->getDbName());
|
||||
|
||||
\$key = \$this->getQueryKey();
|
||||
if (\$key && \$this->cacheContains(\$key)) {
|
||||
\$params = \$this->getParams();
|
||||
\$sql = \$this->cacheFetch(\$key);
|
||||
} else {
|
||||
// check that the columns of the main class are already added (if this is the primary ModelCriteria)
|
||||
if (!\$this->hasSelectClause() && !\$this->getPrimaryCriteria()) {
|
||||
\$this->addSelfSelectColumns();
|
||||
}
|
||||
|
||||
\$this->configureSelectColumns();
|
||||
|
||||
\$needsComplexCount = \$this->getGroupByColumns()
|
||||
|| \$this->getOffset()
|
||||
|| \$this->getLimit()
|
||||
|| \$this->getHaving()
|
||||
|| in_array(Criteria::DISTINCT, \$this->getSelectModifiers());
|
||||
|
||||
\$params = array();
|
||||
if (\$needsComplexCount) {
|
||||
if (\$this->needsSelectAliases()) {
|
||||
if (\$this->getHaving()) {
|
||||
throw new PropelException('Propel cannot create a COUNT query when using HAVING and duplicate column names in the SELECT part');
|
||||
}
|
||||
\$db->turnSelectColumnsToAliases(\$this);
|
||||
}
|
||||
\$selectSql = \$this->createSelectSql(\$params);
|
||||
\$sql = 'SELECT COUNT(*) FROM (' . \$selectSql . ') propelmatch4cnt';
|
||||
} else {
|
||||
// Replace SELECT columns with COUNT(*)
|
||||
\$this->clearSelectColumns()->addSelectColumn('COUNT(*)');
|
||||
\$sql = \$this->createSelectSql(\$params);
|
||||
}
|
||||
|
||||
if (\$key) {
|
||||
\$this->cacheStore(\$key, \$sql);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
\$stmt = \$con->prepare(\$sql);
|
||||
\$db->bindValues(\$stmt, \$params, \$dbMap);
|
||||
\$stmt->execute();
|
||||
} catch (Exception \$e) {
|
||||
Propel::log(\$e->getMessage(), Propel::LOG_ERR);
|
||||
throw new PropelException(sprintf('Unable to execute COUNT statement [%s]', \$sql), 0, \$e);
|
||||
}
|
||||
|
||||
return \$con->getDataFetcher(\$stmt);
|
||||
}
|
||||
";
|
||||
}
|
||||
}
|
||||
350
core/vendor/propel/propel/src/Propel/Generator/Behavior/Sluggable/SluggableBehavior.php
vendored
Normal file
350
core/vendor/propel/propel/src/Propel/Generator/Behavior/Sluggable/SluggableBehavior.php
vendored
Normal file
@@ -0,0 +1,350 @@
|
||||
<?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\Behavior\Sluggable;
|
||||
|
||||
use Propel\Generator\Model\Behavior;
|
||||
use Propel\Generator\Model\Unique;
|
||||
|
||||
/**
|
||||
* Adds a slug column
|
||||
*
|
||||
* @author Francois Zaninotto
|
||||
* @author Massimiliano Arione
|
||||
*/
|
||||
class SluggableBehavior extends Behavior
|
||||
{
|
||||
private $builder;
|
||||
protected $parameters = [
|
||||
'slug_column' => 'slug',
|
||||
'slug_pattern' => '',
|
||||
'replace_pattern' => '/\W+/',
|
||||
'replacement' => '-',
|
||||
'separator' => '-',
|
||||
'permanent' => 'false',
|
||||
'scope_column' => '',
|
||||
];
|
||||
|
||||
/**
|
||||
* Adds the slug_column to the current table.
|
||||
*
|
||||
*/
|
||||
public function modifyTable()
|
||||
{
|
||||
$table = $this->getTable();
|
||||
|
||||
if (!$table->hasColumn($this->getParameter('slug_column'))) {
|
||||
$table->addColumn(array(
|
||||
'name' => $this->getParameter('slug_column'),
|
||||
'type' => 'VARCHAR',
|
||||
'size' => 255,
|
||||
'required' => false,
|
||||
));
|
||||
// add a unique to column
|
||||
$unique = new Unique($this->getColumnForParameter('slug_column'));
|
||||
$unique->setName($table->getCommonName() . '_slug');
|
||||
$unique->addColumn($table->getColumn($this->getParameter('slug_column')));
|
||||
if ($this->getParameter('scope_column')) {
|
||||
$unique->addColumn($table->getColumn($this->getParameter('scope_column')));
|
||||
}
|
||||
$table->addUnique($unique);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the getter of the column of the behavior
|
||||
*
|
||||
* @return string The related getter, e.g. 'getSlug'
|
||||
*/
|
||||
protected function getColumnGetter()
|
||||
{
|
||||
return 'get' . $this->getColumnForParameter('slug_column')->getPhpName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the setter of the column of the behavior
|
||||
*
|
||||
* @return string The related setter, e.g. 'setSlug'
|
||||
*/
|
||||
protected function getColumnSetter()
|
||||
{
|
||||
return 'set' . $this->getColumnForParameter('slug_column')->getPhpName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add code in ObjectBuilder::preSave
|
||||
*
|
||||
* @return string The code to put at the hook
|
||||
*/
|
||||
public function preSave($builder)
|
||||
{
|
||||
$const = $builder->getColumnConstant($this->getColumnForParameter('slug_column'));
|
||||
$script = "
|
||||
if (\$this->isColumnModified($const) && \$this->{$this->getColumnGetter()}()) {
|
||||
\$this->{$this->getColumnSetter()}(\$this->makeSlugUnique(\$this->{$this->getColumnGetter()}()));";
|
||||
if ('true' === $this->getParameter('permanent')) {
|
||||
$script .= "
|
||||
} elseif (!\$this->{$this->getColumnGetter()}()) {
|
||||
\$this->{$this->getColumnSetter()}(\$this->createSlug());
|
||||
}";
|
||||
} else {
|
||||
$script .= "
|
||||
} else {
|
||||
\$this->{$this->getColumnSetter()}(\$this->createSlug());
|
||||
}";
|
||||
}
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
public function objectMethods($builder)
|
||||
{
|
||||
$this->builder = $builder;
|
||||
$script = '';
|
||||
if ('slug' !== $this->getParameter('slug_column')) {
|
||||
$this->addSlugSetter($script);
|
||||
$this->addSlugGetter($script);
|
||||
}
|
||||
$this->addCreateSlug($script);
|
||||
$this->addCreateRawSlug($script);
|
||||
$this->addCleanupSlugPart($script);
|
||||
$this->addLimitSlugSize($script);
|
||||
$this->addMakeSlugUnique($script);
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
protected function addSlugSetter(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Wrap the setter for slug value
|
||||
*
|
||||
* @param string
|
||||
* @return " . $this->getTable()->getPhpName() . "
|
||||
*/
|
||||
public function setSlug(\$v)
|
||||
{
|
||||
return \$this->" . $this->getColumnSetter() . "(\$v);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addSlugGetter(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Wrap the getter for slug value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSlug()
|
||||
{
|
||||
return \$this->" . $this->getColumnGetter() . "();
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addCreateSlug(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Create a unique slug based on the object
|
||||
*
|
||||
* @return string The object slug
|
||||
*/
|
||||
protected function createSlug()
|
||||
{
|
||||
\$slug = \$this->createRawSlug();
|
||||
\$slug = \$this->limitSlugSize(\$slug);
|
||||
\$slug = \$this->makeSlugUnique(\$slug);
|
||||
|
||||
return \$slug;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addCreateRawSlug(&$script)
|
||||
{
|
||||
$pattern = $this->getParameter('slug_pattern');
|
||||
$script .= "
|
||||
/**
|
||||
* Create the slug from the appropriate columns
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function createRawSlug()
|
||||
{
|
||||
";
|
||||
if ($pattern) {
|
||||
$script .= "return '" . str_replace(array('{', '}'), array('\' . $this->cleanupSlugPart($this->get', '()) . \''), $pattern). "';";
|
||||
} else {
|
||||
$script .= "return \$this->cleanupSlugPart(\$this->__toString());";
|
||||
}
|
||||
$script .= "
|
||||
}
|
||||
";
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
public function addCleanupSlugPart(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Cleanup a string to make a slug of it
|
||||
* Removes special characters, replaces blanks with a separator, and trim it
|
||||
*
|
||||
* @param string \$slug the text to slugify
|
||||
* @param string \$replacement the separator used by slug
|
||||
* @return string the slugified text
|
||||
*/
|
||||
protected static function cleanupSlugPart(\$slug, \$replacement = '" . $this->getParameter('replacement') . "')
|
||||
{
|
||||
// transliterate
|
||||
if (function_exists('iconv')) {
|
||||
\$slug = iconv('utf-8', 'us-ascii//TRANSLIT', \$slug);
|
||||
}
|
||||
|
||||
// lowercase
|
||||
if (function_exists('mb_strtolower')) {
|
||||
\$slug = mb_strtolower(\$slug);
|
||||
} else {
|
||||
\$slug = strtolower(\$slug);
|
||||
}
|
||||
|
||||
// remove accents resulting from OSX's iconv
|
||||
\$slug = str_replace(array('\'', '`', '^'), '', \$slug);
|
||||
|
||||
// replace non letter or digits with separator
|
||||
\$slug = preg_replace('" . $this->getParameter('replace_pattern') . "', \$replacement, \$slug);
|
||||
|
||||
// trim
|
||||
\$slug = trim(\$slug, \$replacement);
|
||||
|
||||
if (empty(\$slug)) {
|
||||
return 'n-a';
|
||||
}
|
||||
|
||||
return \$slug;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
public function addLimitSlugSize(&$script)
|
||||
{
|
||||
$size = $this->getColumnForParameter('slug_column')->getSize();
|
||||
$script .= "
|
||||
|
||||
/**
|
||||
* Make sure the slug is short enough to accommodate the column size
|
||||
*
|
||||
* @param string \$slug the slug to check
|
||||
*
|
||||
* @return string the truncated slug
|
||||
*/
|
||||
protected static function limitSlugSize(\$slug, \$incrementReservedSpace = 3)
|
||||
{
|
||||
// check length, as suffix could put it over maximum
|
||||
if (strlen(\$slug) > ($size - \$incrementReservedSpace)) {
|
||||
\$slug = substr(\$slug, 0, $size - \$incrementReservedSpace);
|
||||
}
|
||||
|
||||
return \$slug;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
public function addMakeSlugUnique(&$script)
|
||||
{
|
||||
$script .= "
|
||||
|
||||
/**
|
||||
* Get the slug, ensuring its uniqueness
|
||||
*
|
||||
* @param string \$slug the slug to check
|
||||
* @param string \$separator the separator used by slug
|
||||
* @return string the unique slug
|
||||
*/
|
||||
protected function makeSlugUnique(\$slug, \$separator = '" . $this->getParameter('separator') ."', \$increment = 0)
|
||||
{
|
||||
\$slug2 = empty(\$increment) ? \$slug : \$slug . \$separator . \$increment;
|
||||
\$slugAlreadyExists = " . $this->builder->getQueryClassName() . "::create()
|
||||
->filterBySlug(\$slug2)
|
||||
->prune(\$this)";
|
||||
|
||||
if ($this->getParameter('scope_column')) {
|
||||
$getter = 'get' . $this->getColumnForParameter('scope_column')->getPhpName();
|
||||
$script .="
|
||||
->filterBy('{$this->getColumnForParameter('scope_column')->getPhpName()}', \$this->{$getter}())";
|
||||
}
|
||||
// watch out: some of the columns may be hidden by the soft_delete behavior
|
||||
if ($this->table->hasBehavior('soft_delete')) {
|
||||
$script .= "
|
||||
->includeDeleted()";
|
||||
}
|
||||
$script .= "
|
||||
->count();
|
||||
if (\$slugAlreadyExists) {
|
||||
return \$this->makeSlugUnique(\$slug, \$separator, ++\$increment);
|
||||
} else {
|
||||
return \$slug2;
|
||||
}
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
public function queryMethods($builder)
|
||||
{
|
||||
$this->builder = $builder;
|
||||
$script = '';
|
||||
if ('slug' !== $this->getParameter('slug_column')) {
|
||||
$this->addFilterBySlug($script);
|
||||
}
|
||||
$this->addFindOneBySlug($script);
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
protected function addFilterBySlug(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Filter the query on the slug column
|
||||
*
|
||||
* @param string \$slug The value to use as filter.
|
||||
*
|
||||
* @return " . $this->builder->getQueryClassName() . " The current query, for fluid interface
|
||||
*/
|
||||
public function filterBySlug(\$slug)
|
||||
{
|
||||
return \$this->addUsingAlias(" . $this->builder->getColumnConstant($this->getColumnForParameter('slug_column')) . ", \$slug, Criteria::EQUAL);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addFindOneBySlug(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Find one object based on its slug
|
||||
*
|
||||
* @param string \$slug The value to use as filter.
|
||||
* @param ConnectionInterface \$con The optional connection object
|
||||
*
|
||||
* @return " . $this->builder->getObjectClassName() . " the result, formatted by the current formatter
|
||||
*/
|
||||
public function findOneBySlug(\$slug, \$con = null)
|
||||
{
|
||||
return \$this->filterBySlug(\$slug)->findOne(\$con);
|
||||
}
|
||||
";
|
||||
}
|
||||
}
|
||||
207
core/vendor/propel/propel/src/Propel/Generator/Behavior/Sortable/SortableBehavior.php
vendored
Normal file
207
core/vendor/propel/propel/src/Propel/Generator/Behavior/Sortable/SortableBehavior.php
vendored
Normal file
@@ -0,0 +1,207 @@
|
||||
<?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\Behavior\Sortable;
|
||||
|
||||
use Propel\Generator\Model\Behavior;
|
||||
|
||||
/**
|
||||
* Gives a model class the ability to be ordered
|
||||
* Uses one additional column storing the rank
|
||||
*
|
||||
* @author Massimiliano Arione
|
||||
* @version $Revision$
|
||||
*/
|
||||
class SortableBehavior extends Behavior
|
||||
{
|
||||
// default parameters value
|
||||
protected $parameters = array(
|
||||
'rank_column' => 'sortable_rank',
|
||||
'use_scope' => 'false',
|
||||
'scope_column' => '',
|
||||
);
|
||||
|
||||
protected $objectBuilderModifier;
|
||||
protected $queryBuilderModifier;
|
||||
protected $tableMapBuilderModifier;
|
||||
|
||||
/**
|
||||
* Add the rank_column to the current table
|
||||
*/
|
||||
public function modifyTable()
|
||||
{
|
||||
$table = $this->getTable();
|
||||
|
||||
if (!$table->hasColumn($this->getParameter('rank_column'))) {
|
||||
$table->addColumn(array(
|
||||
'name' => $this->getParameter('rank_column'),
|
||||
'type' => 'INTEGER'
|
||||
));
|
||||
}
|
||||
|
||||
if ($this->useScope()) {
|
||||
if (!$this->hasMultipleScopes() && !$table->hasColumn($this->getParameter('scope_column'))) {
|
||||
$table->addColumn(array(
|
||||
'name' => $this->getParameter('scope_column'),
|
||||
'type' => 'INTEGER'
|
||||
));
|
||||
}
|
||||
|
||||
$scopes = $this->getScopes();
|
||||
if (0 === count($scopes)) {
|
||||
throw new \InvalidArgumentException(sprintf(
|
||||
'The sortable behavior in `%s` needs a `scope_column` parameter.',
|
||||
$this->getTable()->getName()
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getObjectBuilderModifier()
|
||||
{
|
||||
if (null === $this->objectBuilderModifier) {
|
||||
$this->objectBuilderModifier = new SortableBehaviorObjectBuilderModifier($this);
|
||||
}
|
||||
|
||||
return $this->objectBuilderModifier;
|
||||
}
|
||||
|
||||
public function getQueryBuilderModifier()
|
||||
{
|
||||
if (null === $this->queryBuilderModifier) {
|
||||
$this->queryBuilderModifier = new SortableBehaviorQueryBuilderModifier($this);
|
||||
}
|
||||
|
||||
return $this->queryBuilderModifier;
|
||||
}
|
||||
|
||||
public function getTableMapBuilderModifier()
|
||||
{
|
||||
if (null === $this->tableMapBuilderModifier) {
|
||||
$this->tableMapBuilderModifier = new SortableBehaviorTableMapBuilderModifier($this);
|
||||
}
|
||||
|
||||
return $this->tableMapBuilderModifier;
|
||||
}
|
||||
|
||||
public function useScope()
|
||||
{
|
||||
return 'true' === $this->getParameter('use_scope');
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the method argument signature, the appropriate phpDoc for @params,
|
||||
* the scope builder php code and the scope variable builder php code/
|
||||
*
|
||||
* @return array ($methodSignature, $paramsDoc, $scopeBuilder, $buildScopeVars)
|
||||
*/
|
||||
public function generateScopePhp()
|
||||
{
|
||||
|
||||
$methodSignature = '';
|
||||
$paramsDoc = '';
|
||||
$buildScope = '';
|
||||
$buildScopeVars = '';
|
||||
|
||||
if ($this->hasMultipleScopes()) {
|
||||
|
||||
$methodSignature = array();
|
||||
$buildScope = array();
|
||||
$paramsDoc = array();
|
||||
|
||||
foreach ($this->getScopes() as $idx => $scope) {
|
||||
|
||||
$column = $this->table->getColumn($scope);
|
||||
$param = '$scope'.$column->getPhpName();
|
||||
|
||||
$buildScope[] = " \$scope[] = $param;\n";
|
||||
$buildScopeVars[] = " $param = \$scope[$idx];\n";
|
||||
$paramsDoc[] = " * @param ".$column->getPhpType()." $param Scope value for column `".$column->getPhpName()."`";
|
||||
|
||||
if (!$column->isNotNull()) {
|
||||
$param .= ' = null';
|
||||
}
|
||||
$methodSignature[] = $param;
|
||||
}
|
||||
|
||||
$methodSignature = implode(', ', $methodSignature);
|
||||
$paramsDoc = implode("\n", $paramsDoc);
|
||||
$buildScope = "\n".implode('', $buildScope)."\n";
|
||||
$buildScopeVars = "\n".implode('', $buildScopeVars)."\n";
|
||||
|
||||
} elseif ($this->useScope()) {
|
||||
$methodSignature = '$scope';
|
||||
if ($column = $this->table->getColumn($this->getParameter('scope_column'))) {
|
||||
if (!$column->isNotNull()) {
|
||||
$methodSignature .= ' = null';
|
||||
}
|
||||
$paramsDoc .= ' * @param '.$column->getPhpType().' $scope Scope to determine which objects node to return';
|
||||
}
|
||||
}
|
||||
|
||||
return array($methodSignature, $paramsDoc, $buildScope, $buildScopeVars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the getter method name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
public function getColumnGetter($name)
|
||||
{
|
||||
return 'get' . $this->getTable()->getColumn($name)->getPhpName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the setter method name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
public function getColumnSetter($name)
|
||||
{
|
||||
return 'set' . $this->getTable()->getColumn($name)->getPhpName();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addParameter(array $parameter)
|
||||
{
|
||||
if ('scope_column' === $parameter['name']) {
|
||||
$this->parameters['scope_column'] .= ($this->parameters['scope_column'] ? ',' : '') . $parameter['value'];
|
||||
} else {
|
||||
parent::addParameter($parameter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all scope columns as array.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getScopes()
|
||||
{
|
||||
return $this->getParameter('scope_column')
|
||||
? explode(',', str_replace(' ', '', trim($this->getParameter('scope_column'))))
|
||||
: array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the behavior has multiple scope columns.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasMultipleScopes()
|
||||
{
|
||||
return count($this->getScopes()) > 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,833 @@
|
||||
<?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\Behavior\Sortable;
|
||||
|
||||
/**
|
||||
* Behavior to add sortable columns and abilities
|
||||
*
|
||||
* @author François Zaninotto
|
||||
* @author heltem <heltem@o2php.com>
|
||||
*/
|
||||
class SortableBehaviorObjectBuilderModifier
|
||||
{
|
||||
/**
|
||||
* @var SortableBehavior
|
||||
*/
|
||||
protected $behavior;
|
||||
|
||||
/**
|
||||
* @var Table
|
||||
*/
|
||||
protected $table;
|
||||
|
||||
/**
|
||||
* @var Builder
|
||||
*/
|
||||
protected $builder;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $objectClassName;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $tableMapClassName;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $queryClassName;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $queryFullClassName;
|
||||
|
||||
/**
|
||||
* @param SortableBehavior $behavior
|
||||
*/
|
||||
public function __construct($behavior)
|
||||
{
|
||||
$this->behavior = $behavior;
|
||||
$this->table = $behavior->getTable();
|
||||
}
|
||||
|
||||
protected function getParameter($key)
|
||||
{
|
||||
return $this->behavior->getParameter($key);
|
||||
}
|
||||
|
||||
protected function getColumnAttribute($name)
|
||||
{
|
||||
return strtolower($this->behavior->getColumnForParameter($name)->getName());
|
||||
}
|
||||
|
||||
protected function getColumnPhpName($name)
|
||||
{
|
||||
return $this->behavior->getColumnForParameter($name)->getPhpName();
|
||||
}
|
||||
|
||||
protected function setBuilder($builder)
|
||||
{
|
||||
$this->builder = $builder;
|
||||
$this->objectClassName = $builder->getObjectClassName();
|
||||
$this->queryClassName = $builder->getQueryClassName();
|
||||
$this->queryFullClassName = $builder->getStubQueryBuilder()->getFullyQualifiedClassName();
|
||||
$this->tableMapClassName = $builder->getTableMapClassName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the getter of the column of the behavior
|
||||
*
|
||||
* @param string $columnName
|
||||
*
|
||||
* @return string The related getter, e.g. 'getRank'
|
||||
*/
|
||||
protected function getColumnGetter($columnName = 'rank_column')
|
||||
{
|
||||
return 'get' . $this->behavior->getColumnForParameter($columnName)->getPhpName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the setter of the column of the behavior
|
||||
*
|
||||
* @param string $columnName
|
||||
*
|
||||
* @return string The related setter, e.g. 'setRank'
|
||||
*/
|
||||
protected function getColumnSetter($columnName = 'rank_column')
|
||||
{
|
||||
return 'set' . $this->behavior->getColumnForParameter($columnName)->getPhpName();
|
||||
}
|
||||
|
||||
public function preSave($builder)
|
||||
{
|
||||
return "\$this->processSortableQueries(\$con);";
|
||||
}
|
||||
|
||||
public function preInsert($builder)
|
||||
{
|
||||
$useScope = $this->behavior->useScope();
|
||||
$this->setBuilder($builder);
|
||||
|
||||
return "if (!\$this->isColumnModified({$this->tableMapClassName}::RANK_COL)) {
|
||||
\$this->{$this->getColumnSetter()}({$this->queryClassName}::create()->getMaxRankArray(" . ($useScope ? "\$this->getScopeValue(), " : '') . "\$con) + 1);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
public function preUpdate($builder)
|
||||
{
|
||||
if ($this->behavior->useScope()) {
|
||||
$this->setBuilder($builder);
|
||||
|
||||
$condition = array();
|
||||
|
||||
foreach ($this->behavior->getScopes() as $scope) {
|
||||
$condition[] = "\$this->isColumnModified({$this->tableMapClassName}::".strtoupper($scope).")";
|
||||
}
|
||||
|
||||
$condition = implode(' OR ', $condition);
|
||||
|
||||
$script = "// if scope has changed and rank was not modified (if yes, assuming superior action)
|
||||
// insert object to the end of new scope and cleanup old one
|
||||
if (($condition) && !\$this->isColumnModified({$this->tableMapClassName}::RANK_COL)) { {$this->queryClassName}::sortableShiftRank(-1, \$this->{$this->getColumnGetter()}() + 1, null, \$this->oldScope, \$con);
|
||||
\$this->insertAtBottom(\$con);
|
||||
}
|
||||
";
|
||||
|
||||
return $script;
|
||||
}
|
||||
}
|
||||
|
||||
public function preDelete($builder)
|
||||
{
|
||||
$useScope = $this->behavior->useScope();
|
||||
$this->setBuilder($builder);
|
||||
|
||||
return "
|
||||
{$this->queryClassName}::sortableShiftRank(-1, \$this->{$this->getColumnGetter()}() + 1, null, ". ($useScope ? "\$this->getScopeValue(), " : '') . "\$con);
|
||||
{$this->tableMapClassName}::clearInstancePool();
|
||||
";
|
||||
}
|
||||
|
||||
public function objectAttributes($builder)
|
||||
{
|
||||
$script = "
|
||||
/**
|
||||
* Queries to be executed in the save transaction
|
||||
* @var array
|
||||
*/
|
||||
protected \$sortableQueries = array();
|
||||
";
|
||||
if ($this->behavior->useScope()) {
|
||||
$script .= "
|
||||
/**
|
||||
* The old scope value.
|
||||
* @var int
|
||||
*/
|
||||
protected \$oldScope;
|
||||
";
|
||||
}
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
public function objectMethods($builder)
|
||||
{
|
||||
$this->setBuilder($builder);
|
||||
$script = '';
|
||||
if ('rank' !== $this->getParameter('rank_column')) {
|
||||
$this->addRankAccessors($script);
|
||||
}
|
||||
if ($this->behavior->useScope()
|
||||
&& 'scope_value' !== $this->getParameter('scope_column')) {
|
||||
$this->addScopeAccessors($script);
|
||||
}
|
||||
$this->addIsFirst($script);
|
||||
$this->addIsLast($script);
|
||||
$this->addGetNext($script);
|
||||
$this->addGetPrevious($script);
|
||||
$this->addInsertAtRank($script);
|
||||
$this->addInsertAtBottom($script);
|
||||
$this->addInsertAtTop($script);
|
||||
$this->addMoveToRank($script);
|
||||
$this->addSwapWith($script);
|
||||
$this->addMoveUp($script);
|
||||
$this->addMoveDown($script);
|
||||
$this->addMoveToTop($script);
|
||||
$this->addMoveToBottom($script);
|
||||
$this->addRemoveFromList($script);
|
||||
$this->addProcessSortableQueries($script);
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
public function objectFilter(&$script, $builder)
|
||||
{
|
||||
if ($this->behavior->useScope()) {
|
||||
if ($this->behavior->hasMultipleScopes()) {
|
||||
|
||||
foreach ($this->behavior->getScopes() as $idx => $scope) {
|
||||
$name = strtolower($this->behavior->getTable()->getColumn($scope)->getName());
|
||||
|
||||
$search = "if (\$this->$name !== \$v) {";
|
||||
$replace = $search . "
|
||||
// sortable behavior
|
||||
\$this->oldScope[$idx] = \$this->$name;
|
||||
";
|
||||
$script = str_replace($search, $replace, $script);
|
||||
}
|
||||
|
||||
} else {
|
||||
$scope = current($this->behavior->getScopes());
|
||||
$name = strtolower($this->behavior->getTable()->getColumn($scope)->getName());
|
||||
|
||||
$search = "if (\$this->$name !== \$v) {";
|
||||
$replace = $search . "
|
||||
// sortable behavior
|
||||
\$this->oldScope = \$this->$name;
|
||||
";
|
||||
$script = str_replace($search, $replace, $script);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the wraps for getter/setter, if the rank column has not the default name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function addRankAccessors(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Wrap the getter for rank value
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getRank()
|
||||
{
|
||||
return \$this->{$this->getColumnAttribute('rank_column')};
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the setter for rank value
|
||||
*
|
||||
* @param int
|
||||
* @return {$this->objectClassName}
|
||||
*/
|
||||
public function setRank(\$v)
|
||||
{
|
||||
return \$this->{$this->getColumnSetter()}(\$v);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the wraps for getter/setter, if the scope column has not the default name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function addScopeAccessors(&$script)
|
||||
{
|
||||
|
||||
$script .= "
|
||||
/**
|
||||
* Wrap the getter for scope value
|
||||
*
|
||||
* @param boolean \$returnNulls If true and all scope values are null, this will return null instead of a array full with nulls
|
||||
*
|
||||
* @return mixed A array or a native type
|
||||
*/
|
||||
public function getScopeValue(\$returnNulls = true)
|
||||
{
|
||||
";
|
||||
if ($this->behavior->hasMultipleScopes()) {
|
||||
$script .= "
|
||||
\$result = array();
|
||||
\$onlyNulls = true;
|
||||
";
|
||||
foreach ($this->behavior->getScopes() as $scopeField) {
|
||||
$script .= "
|
||||
\$onlyNulls &= null === (\$result[] = \$this->{$this->behavior->getColumnGetter($scopeField)}());
|
||||
";
|
||||
|
||||
}
|
||||
|
||||
$script .= "
|
||||
|
||||
return \$onlyNulls && \$returnNulls ? null : \$result;
|
||||
";
|
||||
} else {
|
||||
|
||||
$script .= "
|
||||
|
||||
return \$this->{$this->getColumnGetter('scope_column')}();
|
||||
";
|
||||
}
|
||||
|
||||
$script .= "
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the setter for scope value
|
||||
*
|
||||
* @param mixed A array or a native type
|
||||
* @return {$this->objectClassName}
|
||||
*/
|
||||
public function setScopeValue(\$v)
|
||||
{
|
||||
";
|
||||
|
||||
if ($this->behavior->hasMultipleScopes()) {
|
||||
|
||||
foreach ($this->behavior->getScopes() as $idx => $scopeField) {
|
||||
$script .= "
|
||||
\$this->{$this->behavior->getColumnSetter($scopeField)}(\$v === null ? null : \$v[$idx]);
|
||||
";
|
||||
}
|
||||
|
||||
} else {
|
||||
$script .= "
|
||||
|
||||
return \$this->{$this->getColumnSetter('scope_column')}(\$v);
|
||||
";
|
||||
|
||||
}
|
||||
$script .= "
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addIsFirst(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Check if the object is first in the list, i.e. if it has 1 for rank
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isFirst()
|
||||
{
|
||||
return \$this->{$this->getColumnGetter()}() == 1;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addIsLast(&$script)
|
||||
{
|
||||
$useScope = $this->behavior->useScope();
|
||||
$script .= "
|
||||
/**
|
||||
* Check if the object is last in the list, i.e. if its rank is the highest rank
|
||||
*
|
||||
* @param ConnectionInterface \$con optional connection
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isLast(ConnectionInterface \$con = null)
|
||||
{
|
||||
return \$this->{$this->getColumnGetter()}() == {$this->queryClassName}::create()->getMaxRankArray(" . ($useScope ? "\$this->getScopeValue(), " : '') . "\$con);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addGetNext(&$script)
|
||||
{
|
||||
$useScope = $this->behavior->useScope();
|
||||
// The generateScopePhp() method below contains the following list of variables:
|
||||
// list($methodSignature, $paramsDoc, $buildScope, $buildScopeVars)
|
||||
list($methodSignature, , , $buildScopeVars) = $this->behavior->generateScopePhp();
|
||||
|
||||
$script .= "
|
||||
/**
|
||||
* Get the next item in the list, i.e. the one for which rank is immediately higher
|
||||
*
|
||||
* @param ConnectionInterface \$con optional connection
|
||||
*
|
||||
* @return {$this->objectClassName}
|
||||
*/
|
||||
public function getNext(ConnectionInterface \$con = null)
|
||||
{";
|
||||
$script .= "
|
||||
|
||||
\$query = {$this->queryClassName}::create();
|
||||
";
|
||||
|
||||
if ($useScope) {
|
||||
$methodSignature = str_replace(' = null', '', $methodSignature);
|
||||
|
||||
$script .= "
|
||||
\$scope = \$this->getScopeValue();
|
||||
$buildScopeVars
|
||||
\$query->filterByRank(\$this->{$this->getColumnGetter()}() + 1, $methodSignature);
|
||||
";
|
||||
} else {
|
||||
|
||||
$script .= "
|
||||
\$query->filterByRank(\$this->{$this->getColumnGetter()}() + 1);
|
||||
";
|
||||
}
|
||||
|
||||
$script .= "
|
||||
|
||||
return \$query->findOne(\$con);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addGetPrevious(&$script)
|
||||
{
|
||||
$useScope = $this->behavior->useScope();
|
||||
|
||||
// The generateScopePhp() method below contains the following list of variables:
|
||||
// list($methodSignature, $paramsDoc, $buildScope, $buildScopeVars)
|
||||
list($methodSignature, , , $buildScopeVars) = $this->behavior->generateScopePhp();
|
||||
|
||||
$script .= "
|
||||
/**
|
||||
* Get the previous item in the list, i.e. the one for which rank is immediately lower
|
||||
*
|
||||
* @param ConnectionInterface \$con optional connection
|
||||
*
|
||||
* @return {$this->objectClassName}
|
||||
*/
|
||||
public function getPrevious(ConnectionInterface \$con = null)
|
||||
{";
|
||||
$script .= "
|
||||
|
||||
\$query = {$this->queryClassName}::create();
|
||||
";
|
||||
|
||||
if ($useScope) {
|
||||
$methodSignature = str_replace(' = null', '', $methodSignature);
|
||||
|
||||
$script .= "
|
||||
\$scope = \$this->getScopeValue();
|
||||
$buildScopeVars
|
||||
\$query->filterByRank(\$this->{$this->getColumnGetter()}() - 1, $methodSignature);
|
||||
";
|
||||
} else {
|
||||
|
||||
$script .= "
|
||||
\$query->filterByRank(\$this->{$this->getColumnGetter()}() - 1);
|
||||
";
|
||||
}
|
||||
|
||||
$script .= "
|
||||
|
||||
return \$query->findOne(\$con);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addInsertAtRank(&$script)
|
||||
{
|
||||
$useScope = $this->behavior->useScope();
|
||||
$queryClassName = $this->queryFullClassName;
|
||||
$script .= "
|
||||
/**
|
||||
* Insert at specified rank
|
||||
* The modifications are not persisted until the object is saved.
|
||||
*
|
||||
* @param integer \$rank rank value
|
||||
* @param ConnectionInterface \$con optional connection
|
||||
*
|
||||
* @return {$this->objectClassName} the current object
|
||||
*
|
||||
* @throws PropelException
|
||||
*/
|
||||
public function insertAtRank(\$rank, ConnectionInterface \$con = null)
|
||||
{";
|
||||
$script .= "
|
||||
\$maxRank = {$this->queryClassName}::create()->getMaxRankArray(" . ($useScope ? "\$this->getScopeValue(), " : '') . "\$con);
|
||||
if (\$rank < 1 || \$rank > \$maxRank + 1) {
|
||||
throw new PropelException('Invalid rank ' . \$rank);
|
||||
}
|
||||
// move the object in the list, at the given rank
|
||||
\$this->{$this->getColumnSetter()}(\$rank);
|
||||
if (\$rank != \$maxRank + 1) {
|
||||
// Keep the list modification query for the save() transaction
|
||||
\$this->sortableQueries []= array(
|
||||
'callable' => array('{$queryClassName}', 'sortableShiftRank'),
|
||||
'arguments' => array(1, \$rank, null, " . ($useScope ? "\$this->getScopeValue()" : '') . ")
|
||||
);
|
||||
}
|
||||
|
||||
return \$this;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addInsertAtBottom(&$script)
|
||||
{
|
||||
$useScope = $this->behavior->useScope();
|
||||
$script .= "
|
||||
/**
|
||||
* Insert in the last rank
|
||||
* The modifications are not persisted until the object is saved.
|
||||
*
|
||||
* @param ConnectionInterface \$con optional connection
|
||||
*
|
||||
* @return {$this->objectClassName} the current object
|
||||
*
|
||||
* @throws PropelException
|
||||
*/
|
||||
public function insertAtBottom(ConnectionInterface \$con = null)
|
||||
{";
|
||||
$script .= "
|
||||
\$this->{$this->getColumnSetter()}({$this->queryClassName}::create()->getMaxRankArray(" . ($useScope ? "\$this->getScopeValue(), " : '') . "\$con) + 1);
|
||||
|
||||
return \$this;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addInsertAtTop(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Insert in the first rank
|
||||
* The modifications are not persisted until the object is saved.
|
||||
*
|
||||
* @return {$this->objectClassName} the current object
|
||||
*/
|
||||
public function insertAtTop()
|
||||
{
|
||||
return \$this->insertAtRank(1);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addMoveToRank(&$script)
|
||||
{
|
||||
$useScope = $this->behavior->useScope();
|
||||
$script .= "
|
||||
/**
|
||||
* Move the object to a new rank, and shifts the rank
|
||||
* Of the objects inbetween the old and new rank accordingly
|
||||
*
|
||||
* @param integer \$newRank rank value
|
||||
* @param ConnectionInterface \$con optional connection
|
||||
*
|
||||
* @return {$this->objectClassName} the current object
|
||||
*
|
||||
* @throws PropelException
|
||||
*/
|
||||
public function moveToRank(\$newRank, ConnectionInterface \$con = null)
|
||||
{
|
||||
if (\$this->isNew()) {
|
||||
throw new PropelException('New objects cannot be moved. Please use insertAtRank() instead');
|
||||
}
|
||||
if (null === \$con) {
|
||||
\$con = Propel::getServiceContainer()->getWriteConnection({$this->tableMapClassName}::DATABASE_NAME);
|
||||
}
|
||||
if (\$newRank < 1 || \$newRank > {$this->queryClassName}::create()->getMaxRankArray(" . ($useScope ? "\$this->getScopeValue(), " : '') . "\$con)) {
|
||||
throw new PropelException('Invalid rank ' . \$newRank);
|
||||
}
|
||||
|
||||
\$oldRank = \$this->{$this->getColumnGetter()}();
|
||||
if (\$oldRank == \$newRank) {
|
||||
return \$this;
|
||||
}
|
||||
|
||||
\$con->beginTransaction();
|
||||
try {
|
||||
// shift the objects between the old and the new rank
|
||||
\$delta = (\$oldRank < \$newRank) ? -1 : 1;
|
||||
{$this->queryClassName}::sortableShiftRank(\$delta, min(\$oldRank, \$newRank), max(\$oldRank, \$newRank), " . ($useScope ? "\$this->getScopeValue(), " : '') . "\$con);
|
||||
|
||||
// move the object to its new rank
|
||||
\$this->{$this->getColumnSetter()}(\$newRank);
|
||||
\$this->save(\$con);
|
||||
|
||||
\$con->commit();
|
||||
|
||||
return \$this;
|
||||
} catch (Exception \$e) {
|
||||
\$con->rollback();
|
||||
throw \$e;
|
||||
}
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addSwapWith(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Exchange the rank of the object with the one passed as argument, and saves both objects
|
||||
*
|
||||
* @param {$this->objectClassName} \$object
|
||||
* @param ConnectionInterface \$con optional connection
|
||||
*
|
||||
* @return {$this->objectClassName} the current object
|
||||
*
|
||||
* @throws Exception if the database cannot execute the two updates
|
||||
*/
|
||||
public function swapWith(\$object, ConnectionInterface \$con = null)
|
||||
{
|
||||
if (null === \$con) {
|
||||
\$con = Propel::getServiceContainer()->getWriteConnection({$this->tableMapClassName}::DATABASE_NAME);
|
||||
}
|
||||
\$con->beginTransaction();
|
||||
try {";
|
||||
if ($this->behavior->useScope()) {
|
||||
$script .= "
|
||||
\$oldScope = \$this->getScopeValue();
|
||||
\$newScope = \$object->getScopeValue();
|
||||
if (\$oldScope != \$newScope) {
|
||||
\$this->setScopeValue(\$newScope);
|
||||
\$object->setScopeValue(\$oldScope);
|
||||
}";
|
||||
}
|
||||
|
||||
$script .= "
|
||||
\$oldRank = \$this->{$this->getColumnGetter()}();
|
||||
\$newRank = \$object->{$this->getColumnGetter()}();
|
||||
|
||||
\$this->{$this->getColumnSetter()}(\$newRank);
|
||||
\$object->{$this->getColumnSetter()}(\$oldRank);
|
||||
|
||||
\$this->save(\$con);
|
||||
\$object->save(\$con);
|
||||
\$con->commit();
|
||||
|
||||
return \$this;
|
||||
} catch (Exception \$e) {
|
||||
\$con->rollback();
|
||||
throw \$e;
|
||||
}
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addMoveUp(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Move the object higher in the list, i.e. exchanges its rank with the one of the previous object
|
||||
*
|
||||
* @param ConnectionInterface \$con optional connection
|
||||
*
|
||||
* @return {$this->objectClassName} the current object
|
||||
*/
|
||||
public function moveUp(ConnectionInterface \$con = null)
|
||||
{
|
||||
if (\$this->isFirst()) {
|
||||
return \$this;
|
||||
}
|
||||
if (null === \$con) {
|
||||
\$con = Propel::getServiceContainer()->getWriteConnection({$this->tableMapClassName}::DATABASE_NAME);
|
||||
}
|
||||
\$con->beginTransaction();
|
||||
try {
|
||||
\$prev = \$this->getPrevious(\$con);
|
||||
\$this->swapWith(\$prev, \$con);
|
||||
\$con->commit();
|
||||
|
||||
return \$this;
|
||||
} catch (Exception \$e) {
|
||||
\$con->rollback();
|
||||
throw \$e;
|
||||
}
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addMoveDown(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Move the object higher in the list, i.e. exchanges its rank with the one of the next object
|
||||
*
|
||||
* @param ConnectionInterface \$con optional connection
|
||||
*
|
||||
* @return {$this->objectClassName} the current object
|
||||
*/
|
||||
public function moveDown(ConnectionInterface \$con = null)
|
||||
{
|
||||
if (\$this->isLast(\$con)) {
|
||||
return \$this;
|
||||
}
|
||||
if (null === \$con) {
|
||||
\$con = Propel::getServiceContainer()->getWriteConnection({$this->tableMapClassName}::DATABASE_NAME);
|
||||
}
|
||||
\$con->beginTransaction();
|
||||
try {
|
||||
\$next = \$this->getNext(\$con);
|
||||
\$this->swapWith(\$next, \$con);
|
||||
\$con->commit();
|
||||
|
||||
return \$this;
|
||||
} catch (Exception \$e) {
|
||||
\$con->rollback();
|
||||
throw \$e;
|
||||
}
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addMoveToTop(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Move the object to the top of the list
|
||||
*
|
||||
* @param ConnectionInterface \$con optional connection
|
||||
*
|
||||
* @return {$this->objectClassName} the current object
|
||||
*/
|
||||
public function moveToTop(ConnectionInterface \$con = null)
|
||||
{
|
||||
if (\$this->isFirst()) {
|
||||
return \$this;
|
||||
}
|
||||
|
||||
return \$this->moveToRank(1, \$con);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addMoveToBottom(&$script)
|
||||
{
|
||||
$useScope = $this->behavior->useScope();
|
||||
$script .= "
|
||||
/**
|
||||
* Move the object to the bottom of the list
|
||||
*
|
||||
* @param ConnectionInterface \$con optional connection
|
||||
*
|
||||
* @return integer the old object's rank
|
||||
*/
|
||||
public function moveToBottom(ConnectionInterface \$con = null)
|
||||
{
|
||||
if (\$this->isLast(\$con)) {
|
||||
return false;
|
||||
}
|
||||
if (null === \$con) {
|
||||
\$con = Propel::getServiceContainer()->getWriteConnection({$this->tableMapClassName}::DATABASE_NAME);
|
||||
}
|
||||
\$con->beginTransaction();
|
||||
try {
|
||||
\$bottom = {$this->queryClassName}::create()->getMaxRankArray(" . ($useScope ? "\$this->getScopeValue(), " : '') . "\$con);
|
||||
\$res = \$this->moveToRank(\$bottom, \$con);
|
||||
\$con->commit();
|
||||
|
||||
return \$res;
|
||||
} catch (Exception \$e) {
|
||||
\$con->rollback();
|
||||
throw \$e;
|
||||
}
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addRemoveFromList(&$script)
|
||||
{
|
||||
$useScope = $this->behavior->useScope();
|
||||
$script .= "
|
||||
/**
|
||||
* Removes the current object from the list".($useScope ? ' (moves it to the null scope)' : '').".
|
||||
* The modifications are not persisted until the object is saved.
|
||||
*
|
||||
* @return {$this->objectClassName} the current object
|
||||
*/
|
||||
public function removeFromList()
|
||||
{";
|
||||
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
// check if object is already removed
|
||||
if (\$this->getScopeValue() === null) {
|
||||
throw new PropelException('Object is already removed (has null scope)');
|
||||
}
|
||||
|
||||
// move the object to the end of null scope
|
||||
\$this->setScopeValue(null);";
|
||||
} else {
|
||||
$script .= "
|
||||
// Keep the list modification query for the save() transaction
|
||||
\$this->sortableQueries[] = array(
|
||||
'callable' => array('{$this->queryFullClassName}', 'sortableShiftRank'),
|
||||
'arguments' => array(-1, \$this->{$this->getColumnGetter()}() + 1, null" . ($useScope ? ", \$this->getScopeValue()" : '') . ")
|
||||
);
|
||||
// remove the object from the list
|
||||
\$this->{$this->getColumnSetter('rank_column')}(null);
|
||||
";
|
||||
}
|
||||
$script .= "
|
||||
|
||||
return \$this;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addProcessSortableQueries(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Execute queries that were saved to be run inside the save transaction
|
||||
*/
|
||||
protected function processSortableQueries(\$con)
|
||||
{
|
||||
foreach (\$this->sortableQueries as \$query) {
|
||||
\$query['arguments'][]= \$con;
|
||||
call_user_func_array(\$query['callable'], \$query['arguments']);
|
||||
}
|
||||
\$this->sortableQueries = array();
|
||||
}
|
||||
";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,602 @@
|
||||
<?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\Behavior\Sortable;
|
||||
|
||||
/**
|
||||
* Behavior to add sortable query methods
|
||||
*
|
||||
* @author François Zaninotto
|
||||
*/
|
||||
class SortableBehaviorQueryBuilderModifier
|
||||
{
|
||||
protected $behavior;
|
||||
|
||||
protected $table;
|
||||
|
||||
protected $builder;
|
||||
|
||||
protected $objectClassName;
|
||||
|
||||
protected $queryClassName;
|
||||
|
||||
protected $tableMapClassName;
|
||||
|
||||
public function __construct($behavior)
|
||||
{
|
||||
$this->behavior = $behavior;
|
||||
$this->table = $behavior->getTable();
|
||||
}
|
||||
|
||||
protected function getParameter($key)
|
||||
{
|
||||
return $this->behavior->getParameter($key);
|
||||
}
|
||||
|
||||
protected function getColumn($name)
|
||||
{
|
||||
return $this->behavior->getColumnForParameter($name);
|
||||
}
|
||||
|
||||
protected function setBuilder($builder)
|
||||
{
|
||||
$this->builder = $builder;
|
||||
$this->objectClassName = $builder->getObjectClassName();
|
||||
$this->queryClassName = $builder->getQueryClassName();
|
||||
$this->tableMapClassName = $builder->getTableMapClassName();
|
||||
}
|
||||
|
||||
public function queryMethods($builder)
|
||||
{
|
||||
|
||||
$this->setBuilder($builder);
|
||||
$this->builder->declareClasses(
|
||||
'\Propel\Runtime\Propel',
|
||||
'\Propel\Runtime\Connection\ConnectionInterface'
|
||||
);
|
||||
$script = '';
|
||||
|
||||
// select filters
|
||||
if ($this->behavior->useScope()) {
|
||||
$this->addInList($script);
|
||||
}
|
||||
if ('rank' !== $this->getParameter('rank_column')) {
|
||||
$this->addFilterByRank($script);
|
||||
$this->addOrderByRank($script);
|
||||
}
|
||||
|
||||
// select termination methods
|
||||
if ('rank' !== $this->getParameter('rank_column')
|
||||
|| $this->behavior->useScope()) {
|
||||
$this->addFindOneByRank($script);
|
||||
}
|
||||
$this->addFindList($script);
|
||||
|
||||
// utilities
|
||||
$this->addGetMaxRank($script);
|
||||
$this->addGetMaxRankArray($script);
|
||||
$this->addRetrieveByRank($script);
|
||||
$this->addReorder($script);
|
||||
$this->addDoSelectOrderByRank($script);
|
||||
if ($this->behavior->useScope()) {
|
||||
$this->addRetrieveList($script);
|
||||
$this->addCountList($script);
|
||||
$this->addDeleteList($script);
|
||||
$this->addSortableApplyScopeCriteria($script);
|
||||
}
|
||||
$this->addShiftRank($script);
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
public function addSortableApplyScopeCriteria(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Applies all scope fields to the given criteria.
|
||||
*
|
||||
* @param Criteria \$criteria Applies the values directly to this criteria.
|
||||
* @param mixed \$scope The scope value as scalar type or array(\$value1, ...).
|
||||
* @param string \$method The method we use to apply the values.
|
||||
*
|
||||
*/
|
||||
static public function sortableApplyScopeCriteria(Criteria \$criteria, \$scope, \$method = 'add')
|
||||
{
|
||||
";
|
||||
if ($this->behavior->hasMultipleScopes()) {
|
||||
foreach ($this->behavior->getScopes() as $idx => $scope) {
|
||||
$script .= "
|
||||
\$criteria->\$method({$this->tableMapClassName}::".strtoupper($scope).", \$scope[$idx], Criteria::EQUAL);
|
||||
";
|
||||
}
|
||||
} else {
|
||||
$script .= "
|
||||
\$criteria->\$method({$this->tableMapClassName}::".strtoupper(current($this->behavior->getScopes())).", \$scope, Criteria::EQUAL);
|
||||
";
|
||||
}
|
||||
|
||||
$script .= "
|
||||
}
|
||||
";
|
||||
|
||||
}
|
||||
|
||||
protected function addInList(&$script)
|
||||
{
|
||||
list($methodSignature, $paramsDoc, $buildScope) = $this->behavior->generateScopePhp();
|
||||
$script .= "
|
||||
/**
|
||||
* Returns the objects in a certain list, from the list scope
|
||||
*
|
||||
$paramsDoc
|
||||
*
|
||||
* @return {$this->queryClassName} The current query, for fluid interface
|
||||
*/
|
||||
public function inList($methodSignature)
|
||||
{
|
||||
$buildScope
|
||||
static::sortableApplyScopeCriteria(\$this, \$scope, 'addUsingAlias');
|
||||
|
||||
return \$this;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addFilterByRank(&$script)
|
||||
{
|
||||
$useScope = $this->behavior->useScope();
|
||||
if ($useScope) {
|
||||
list($methodSignature, $paramsDoc) = $this->behavior->generateScopePhp();
|
||||
}
|
||||
|
||||
$script .= "
|
||||
/**
|
||||
* Filter the query based on a rank in the list
|
||||
*
|
||||
* @param integer \$rank rank";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
$paramsDoc
|
||||
";
|
||||
}
|
||||
$script .= "
|
||||
*
|
||||
* @return " . $this->queryClassName . " The current query, for fluid interface
|
||||
*/
|
||||
public function filterByRank(\$rank" . ($useScope ? ", $methodSignature" : "") . ")
|
||||
{";
|
||||
|
||||
if ($useScope) {
|
||||
$methodSignature = str_replace(' = null', '', $methodSignature);
|
||||
}
|
||||
|
||||
$script .= "
|
||||
|
||||
return \$this";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
->inList($methodSignature)";
|
||||
}
|
||||
$script .= "
|
||||
->addUsingAlias({$this->tableMapClassName}::RANK_COL, \$rank, Criteria::EQUAL);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addOrderByRank(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Order the query based on the rank in the list.
|
||||
* Using the default \$order, returns the item with the lowest rank first
|
||||
*
|
||||
* @param string \$order either Criteria::ASC (default) or Criteria::DESC
|
||||
*
|
||||
* @return " . $this->queryClassName . " The current query, for fluid interface
|
||||
*/
|
||||
public function orderByRank(\$order = Criteria::ASC)
|
||||
{
|
||||
\$order = strtoupper(\$order);
|
||||
switch (\$order) {
|
||||
case Criteria::ASC:
|
||||
return \$this->addAscendingOrderByColumn(\$this->getAliasedColName({$this->tableMapClassName}::RANK_COL));
|
||||
break;
|
||||
case Criteria::DESC:
|
||||
return \$this->addDescendingOrderByColumn(\$this->getAliasedColName({$this->tableMapClassName}::RANK_COL));
|
||||
break;
|
||||
default:
|
||||
throw new \Propel\Runtime\Exception\PropelException('{$this->queryClassName}::orderBy() only accepts \"asc\" or \"desc\" as argument');
|
||||
}
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addFindOneByRank(&$script)
|
||||
{
|
||||
$useScope = $this->behavior->useScope();
|
||||
if ($useScope) {
|
||||
list($methodSignature, $paramsDoc, ) = $this->behavior->generateScopePhp();
|
||||
}
|
||||
|
||||
$script .= "
|
||||
/**
|
||||
* Get an item from the list based on its rank
|
||||
*
|
||||
* @param integer \$rank rank";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
$paramsDoc";
|
||||
}
|
||||
$script .= "
|
||||
* @param ConnectionInterface \$con optional connection
|
||||
*
|
||||
* @return {$this->objectClassName}
|
||||
*/
|
||||
public function findOneByRank(\$rank, " . ($useScope ? "$methodSignature, " : "") . "ConnectionInterface \$con = null)
|
||||
{";
|
||||
if ($useScope) {
|
||||
$methodSignature = str_replace(' = null', '', $methodSignature);
|
||||
}
|
||||
|
||||
$script .= "
|
||||
|
||||
return \$this
|
||||
->filterByRank(\$rank" . ($useScope ? ", $methodSignature" : "") . ")
|
||||
->findOne(\$con);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addFindList(&$script)
|
||||
{
|
||||
$useScope = $this->behavior->useScope();
|
||||
if ($useScope) {
|
||||
list($methodSignature, $paramsDoc) = $this->behavior->generateScopePhp();
|
||||
}
|
||||
|
||||
$script .= "
|
||||
/**
|
||||
* Returns " . ($useScope ? 'a' : 'the') ." list of objects
|
||||
*";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
$paramsDoc
|
||||
";
|
||||
}
|
||||
|
||||
$script .= "
|
||||
* @param ConnectionInterface \$con Connection to use.
|
||||
*
|
||||
* @return mixed the list of results, formatted by the current formatter
|
||||
*/
|
||||
public function findList(" . ($useScope ? "$methodSignature, " : "") . "\$con = null)
|
||||
{";
|
||||
|
||||
if ($useScope) {
|
||||
$methodSignature = str_replace(' = null', '', $methodSignature);
|
||||
}
|
||||
|
||||
$script .= "
|
||||
|
||||
return \$this";
|
||||
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
->inList($methodSignature)";
|
||||
}
|
||||
$script .= "
|
||||
->orderByRank()
|
||||
->find(\$con);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addGetMaxRank(&$script)
|
||||
{
|
||||
$useScope = $this->behavior->useScope();
|
||||
if ($useScope) {
|
||||
list($methodSignature, $paramsDoc, $buildScope) = $this->behavior->generateScopePhp();
|
||||
}
|
||||
|
||||
$script .= "
|
||||
/**
|
||||
* Get the highest rank
|
||||
* ";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
$paramsDoc";
|
||||
}
|
||||
$script .= "
|
||||
* @param ConnectionInterface optional connection
|
||||
*
|
||||
* @return integer highest position
|
||||
*/
|
||||
public function getMaxRank(" . ($useScope ? "$methodSignature, " : "") . "ConnectionInterface \$con = null)
|
||||
{
|
||||
if (null === \$con) {
|
||||
\$con = Propel::getServiceContainer()->getReadConnection({$this->tableMapClassName}::DATABASE_NAME);
|
||||
}
|
||||
// shift the objects with a position lower than the one of object
|
||||
\$this->addSelectColumn('MAX(' . {$this->tableMapClassName}::RANK_COL . ')');";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
$buildScope
|
||||
static::sortableApplyScopeCriteria(\$this, \$scope);";
|
||||
}
|
||||
$script .= "
|
||||
\$stmt = \$this->doSelect(\$con);
|
||||
|
||||
return \$stmt->fetchColumn();
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addGetMaxRankArray(&$script)
|
||||
{
|
||||
$useScope = $this->behavior->useScope();
|
||||
|
||||
$script .= "
|
||||
/**
|
||||
* Get the highest rank by a scope with a array format.
|
||||
* ";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
* @param mixed \$scope The scope value as scalar type or array(\$value1, ...).
|
||||
";
|
||||
}
|
||||
$script .= "
|
||||
* @param ConnectionInterface optional connection
|
||||
*
|
||||
* @return integer highest position
|
||||
*/
|
||||
public function getMaxRankArray(" . ($useScope ? "\$scope, " : "") . "ConnectionInterface \$con = null)
|
||||
{
|
||||
if (\$con === null) {
|
||||
\$con = Propel::getConnection({$this->tableMapClassName}::DATABASE_NAME);
|
||||
}
|
||||
// shift the objects with a position lower than the one of object
|
||||
\$this->addSelectColumn('MAX(' . {$this->tableMapClassName}::RANK_COL . ')');";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
static::sortableApplyScopeCriteria(\$this, \$scope);";
|
||||
}
|
||||
$script .= "
|
||||
\$stmt = \$this->doSelect(\$con);
|
||||
|
||||
return \$stmt->fetchColumn();
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addReorder(&$script)
|
||||
{
|
||||
$columnGetter = 'get' . $this->behavior->getColumnForParameter('rank_column')->getPhpName();
|
||||
$columnSetter = 'set' . $this->behavior->getColumnForParameter('rank_column')->getPhpName();
|
||||
$script .= "
|
||||
/**
|
||||
* Reorder a set of sortable objects based on a list of id/position
|
||||
* Beware that there is no check made on the positions passed
|
||||
* So incoherent positions will result in an incoherent list
|
||||
*
|
||||
* @param mixed \$order id => rank pairs
|
||||
* @param ConnectionInterface \$con optional connection
|
||||
*
|
||||
* @return boolean true if the reordering took place, false if a database problem prevented it
|
||||
*/
|
||||
public function reorder(\$order, ConnectionInterface \$con = null)
|
||||
{
|
||||
if (null === \$con) {
|
||||
\$con = Propel::getServiceContainer()->getReadConnection({$this->tableMapClassName}::DATABASE_NAME);
|
||||
}
|
||||
|
||||
\$con->beginTransaction();
|
||||
try {
|
||||
\$ids = array_keys(\$order);
|
||||
\$objects = \$this->findPks(\$ids, \$con);
|
||||
foreach (\$objects as \$object) {
|
||||
\$pk = \$object->getPrimaryKey();
|
||||
if (\$object->$columnGetter() != \$order[\$pk]) {
|
||||
\$object->$columnSetter(\$order[\$pk]);
|
||||
\$object->save(\$con);
|
||||
}
|
||||
}
|
||||
\$con->commit();
|
||||
|
||||
return true;
|
||||
} catch (\Propel\Runtime\Exception\PropelException \$e) {
|
||||
\$con->rollback();
|
||||
throw \$e;
|
||||
}
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addRetrieveByRank(&$script)
|
||||
{
|
||||
$useScope = $this->behavior->useScope();
|
||||
$script .= "
|
||||
/**
|
||||
* Get an item from the list based on its rank
|
||||
*
|
||||
* @param integer \$rank rank";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
* @param int \$scope Scope to determine which suite to consider";
|
||||
}
|
||||
$script .= "
|
||||
* @param ConnectionInterface \$con optional connection
|
||||
*
|
||||
* @return {$this->objectClassName}
|
||||
*/
|
||||
static public function retrieveByRank(\$rank, " . ($useScope ? "\$scope = null, " : "") . "ConnectionInterface \$con = null)
|
||||
{
|
||||
if (null === \$con) {
|
||||
\$con = Propel::getServiceContainer()->getReadConnection({$this->tableMapClassName}::DATABASE_NAME);
|
||||
}
|
||||
|
||||
\$c = new Criteria;
|
||||
\$c->add({$this->tableMapClassName}::RANK_COL, \$rank);";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
static::sortableApplyScopeCriteria(\$c, \$scope);";
|
||||
}
|
||||
$script .= "
|
||||
|
||||
return static::create(null, \$c)->findOne(\$con);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addDoSelectOrderByRank(&$script)
|
||||
{
|
||||
$queryClassName = $this->queryClassName;
|
||||
$script .= "
|
||||
/**
|
||||
* Return an array of sortable objects ordered by position
|
||||
*
|
||||
* @param Criteria \$criteria optional criteria object
|
||||
* @param string \$order sorting order, to be chosen between Criteria::ASC (default) and Criteria::DESC
|
||||
* @param ConnectionInterface \$con optional connection
|
||||
*
|
||||
* @return array list of sortable objects
|
||||
*/
|
||||
static public function doSelectOrderByRank(Criteria \$criteria = null, \$order = Criteria::ASC, ConnectionInterface \$con = null)
|
||||
{
|
||||
if (null === \$con) {
|
||||
\$con = Propel::getServiceContainer()->getReadConnection({$this->tableMapClassName}::DATABASE_NAME);
|
||||
}
|
||||
|
||||
if (null === \$criteria) {
|
||||
\$criteria = new Criteria();
|
||||
} elseif (\$criteria instanceof Criteria) {
|
||||
\$criteria = clone \$criteria;
|
||||
}
|
||||
|
||||
\$criteria->clearOrderByColumns();
|
||||
|
||||
if (Criteria::ASC == \$order) {
|
||||
\$criteria->addAscendingOrderByColumn({$this->tableMapClassName}::RANK_COL);
|
||||
} else {
|
||||
\$criteria->addDescendingOrderByColumn({$this->tableMapClassName}::RANK_COL);
|
||||
}
|
||||
|
||||
return $queryClassName::create(null, \$criteria)->find(\$con);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addRetrieveList(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Return an array of sortable objects in the given scope ordered by position
|
||||
*
|
||||
* @param int \$scope the scope of the list
|
||||
* @param string \$order sorting order, to be chosen between Criteria::ASC (default) and Criteria::DESC
|
||||
* @param ConnectionInterface \$con optional connection
|
||||
*
|
||||
* @return array list of sortable objects
|
||||
*/
|
||||
static public function retrieveList(\$scope, \$order = Criteria::ASC, ConnectionInterface \$con = null)
|
||||
{
|
||||
\$c = new Criteria();
|
||||
static::sortableApplyScopeCriteria(\$c, \$scope);
|
||||
|
||||
return {$this->queryClassName}::doSelectOrderByRank(\$c, \$order, \$con);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addCountList(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Return the number of sortable objects in the given scope
|
||||
*
|
||||
* @param int \$scope the scope of the list
|
||||
* @param ConnectionInterface \$con optional connection
|
||||
*
|
||||
* @return array list of sortable objects
|
||||
*/
|
||||
static public function countList(\$scope, ConnectionInterface \$con = null)
|
||||
{
|
||||
\$c = new Criteria();
|
||||
\$c->add({$this->tableMapClassName}::SCOPE_COL, \$scope);
|
||||
|
||||
return {$this->queryClassName}::create(null, \$c)->count(\$con);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addDeleteList(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Deletes the sortable objects in the given scope
|
||||
*
|
||||
* @param int \$scope the scope of the list
|
||||
* @param ConnectionInterface \$con optional connection
|
||||
*
|
||||
* @return int number of deleted objects
|
||||
*/
|
||||
static public function deleteList(\$scope, ConnectionInterface \$con = null)
|
||||
{
|
||||
\$c = new Criteria();
|
||||
static::sortableApplyScopeCriteria(\$c, \$scope);
|
||||
|
||||
return {$this->tableMapClassName}::doDelete(\$c, \$con);
|
||||
}
|
||||
";
|
||||
}
|
||||
protected function addShiftRank(&$script)
|
||||
{
|
||||
$useScope = $this->behavior->useScope();
|
||||
$script .= "
|
||||
/**
|
||||
* Adds \$delta to all Rank values that are >= \$first and <= \$last.
|
||||
* '\$delta' can also be negative.
|
||||
*
|
||||
* @param int \$delta Value to be shifted by, can be negative
|
||||
* @param int \$first First node to be shifted
|
||||
* @param int \$last Last node to be shifted";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
* @param int \$scope Scope to use for the shift";
|
||||
}
|
||||
$script .= "
|
||||
* @param ConnectionInterface \$con Connection to use.
|
||||
*/
|
||||
static public function sortableShiftRank(\$delta, \$first, \$last = null, " . ($useScope ? "\$scope = null, " : "") . "ConnectionInterface \$con = null)
|
||||
{
|
||||
if (null === \$con) {
|
||||
\$con = Propel::getServiceContainer()->getWriteConnection({$this->tableMapClassName}::DATABASE_NAME);
|
||||
}
|
||||
|
||||
\$whereCriteria = new Criteria({$this->tableMapClassName}::DATABASE_NAME);
|
||||
\$criterion = \$whereCriteria->getNewCriterion({$this->tableMapClassName}::RANK_COL, \$first, Criteria::GREATER_EQUAL);
|
||||
if (null !== \$last) {
|
||||
\$criterion->addAnd(\$whereCriteria->getNewCriterion({$this->tableMapClassName}::RANK_COL, \$last, Criteria::LESS_EQUAL));
|
||||
}
|
||||
\$whereCriteria->add(\$criterion);";
|
||||
if ($useScope) {
|
||||
$script .= "
|
||||
static::sortableApplyScopeCriteria(\$whereCriteria, \$scope);";
|
||||
}
|
||||
$script .= "
|
||||
|
||||
\$valuesCriteria = new Criteria({$this->tableMapClassName}::DATABASE_NAME);
|
||||
\$valuesCriteria->add({$this->tableMapClassName}::RANK_COL, array('raw' => {$this->tableMapClassName}::RANK_COL . ' + ?', 'value' => \$delta), Criteria::CUSTOM_EQUAL);
|
||||
|
||||
\$whereCriteria->doUpdate(\$valuesCriteria, \$con);
|
||||
{$this->tableMapClassName}::clearInstancePool();
|
||||
}
|
||||
";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?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\Behavior\Sortable;
|
||||
|
||||
/**
|
||||
* Behavior to add sortable methods
|
||||
*
|
||||
* @author Jérémie Augustin
|
||||
*/
|
||||
class SortableBehaviorTableMapBuilderModifier
|
||||
{
|
||||
/**
|
||||
* @var SortableBehavior
|
||||
*/
|
||||
protected $behavior;
|
||||
|
||||
protected $table;
|
||||
|
||||
public function __construct($behavior)
|
||||
{
|
||||
$this->behavior = $behavior;
|
||||
$this->table = $behavior->getTable();
|
||||
}
|
||||
|
||||
public function staticAttributes($builder)
|
||||
{
|
||||
$tableName = $this->table->getName();
|
||||
$col = '';
|
||||
|
||||
if ($this->behavior->useScope()) {
|
||||
|
||||
if ($this->behavior->hasMultipleScopes()) {
|
||||
foreach ($this->behavior->getScopes() as $scope) {
|
||||
$col[] = "$tableName.".strtoupper($scope);
|
||||
}
|
||||
$col = json_encode($col);
|
||||
$col = "'$col'";
|
||||
} else {
|
||||
$colNames = $this->getColumnConstant('scope_column');
|
||||
$col = "'$tableName.$colNames'";
|
||||
}
|
||||
}
|
||||
|
||||
return $this->behavior->renderTemplate('tableMapSortable', array(
|
||||
'rankColumn' => $this->getColumnConstant('rank_column'),
|
||||
'multiScope' => $this->behavior->hasMultipleScopes(),
|
||||
'scope' => $col,
|
||||
'tableName' => $this->table->getName(),
|
||||
'useScope' => $this->behavior->useScope(),
|
||||
));
|
||||
}
|
||||
|
||||
protected function getColumnConstant($name)
|
||||
{
|
||||
return strtoupper($this->behavior->getColumnForParameter($name)->getName());
|
||||
}
|
||||
|
||||
}
|
||||
22
core/vendor/propel/propel/src/Propel/Generator/Behavior/Sortable/templates/tableMapSortable.php
vendored
Normal file
22
core/vendor/propel/propel/src/Propel/Generator/Behavior/Sortable/templates/tableMapSortable.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* rank column
|
||||
*/
|
||||
const RANK_COL = "<?php echo $tableName ?>.<?php echo $rankColumn ?>";
|
||||
|
||||
<?php if ($useScope) :?>
|
||||
|
||||
<?php if ($multiScope) :?>
|
||||
/**
|
||||
* If defined, the `SCOPE_COL` contains a json_encoded array with all columns.
|
||||
* @var boolean
|
||||
*/
|
||||
const MULTI_SCOPE_COL = true;
|
||||
|
||||
<?php endif?>
|
||||
|
||||
/**
|
||||
* Scope column for the set
|
||||
*/
|
||||
const SCOPE_COL = <?php echo $scope ?>;
|
||||
|
||||
<?php endif ?>
|
||||
181
core/vendor/propel/propel/src/Propel/Generator/Behavior/Timestampable/TimestampableBehavior.php
vendored
Normal file
181
core/vendor/propel/propel/src/Propel/Generator/Behavior/Timestampable/TimestampableBehavior.php
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
<?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\Behavior\Timestampable;
|
||||
|
||||
use Propel\Generator\Model\Behavior;
|
||||
|
||||
/**
|
||||
* Gives a model class the ability to track creation and last modification dates
|
||||
* Uses two additional columns storing the creation and update date
|
||||
*
|
||||
* @author François Zaninotto
|
||||
*/
|
||||
class TimestampableBehavior extends Behavior
|
||||
{
|
||||
protected $parameters = [
|
||||
'create_column' => 'created_at',
|
||||
'update_column' => 'updated_at',
|
||||
];
|
||||
|
||||
/**
|
||||
* Add the create_column and update_columns to the current table
|
||||
*/
|
||||
public function modifyTable()
|
||||
{
|
||||
$table = $this->getTable();
|
||||
|
||||
if (!$table->hasColumn($this->getParameter('create_column'))) {
|
||||
$table->addColumn(array(
|
||||
'name' => $this->getParameter('create_column'),
|
||||
'type' => 'TIMESTAMP'
|
||||
));
|
||||
}
|
||||
if (!$table->hasColumn($this->getParameter('update_column'))) {
|
||||
$table->addColumn(array(
|
||||
'name' => $this->getParameter('update_column'),
|
||||
'type' => 'TIMESTAMP'
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the setter of one of the columns of the behavior
|
||||
*
|
||||
* @param string $column One of the behavior columns, 'create_column' or 'update_column'
|
||||
* @return string The related setter, 'setCreatedOn' or 'setUpdatedOn'
|
||||
*/
|
||||
protected function getColumnSetter($column)
|
||||
{
|
||||
return 'set' . $this->getColumnForParameter($column)->getPhpName();
|
||||
}
|
||||
|
||||
protected function getColumnConstant($columnName, $builder)
|
||||
{
|
||||
return $builder->getColumnConstant($this->getColumnForParameter($columnName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add code in ObjectBuilder::preUpdate
|
||||
*
|
||||
* @return string The code to put at the hook
|
||||
*/
|
||||
public function preUpdate($builder)
|
||||
{
|
||||
return "if (\$this->isModified() && !\$this->isColumnModified(" . $this->getColumnConstant('update_column', $builder) . ")) {
|
||||
\$this->" . $this->getColumnSetter('update_column') . "(time());
|
||||
}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Add code in ObjectBuilder::preInsert
|
||||
*
|
||||
* @return string The code to put at the hook
|
||||
*/
|
||||
public function preInsert($builder)
|
||||
{
|
||||
return "if (!\$this->isColumnModified(" . $this->getColumnConstant('create_column', $builder) . ")) {
|
||||
\$this->" . $this->getColumnSetter('create_column') . "(time());
|
||||
}
|
||||
if (!\$this->isColumnModified(" . $this->getColumnConstant('update_column', $builder) . ")) {
|
||||
\$this->" . $this->getColumnSetter('update_column') . "(time());
|
||||
}";
|
||||
}
|
||||
|
||||
public function objectMethods($builder)
|
||||
{
|
||||
return "
|
||||
/**
|
||||
* Mark the current object so that the update date doesn't get updated during next save
|
||||
*
|
||||
* @return " . $builder->getObjectClassName() . " The current object (for fluent API support)
|
||||
*/
|
||||
public function keepUpdateDateUnchanged()
|
||||
{
|
||||
\$this->modifiedColumns[" . $this->getColumnConstant('update_column', $builder) . "] = true;
|
||||
|
||||
return \$this;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
public function queryMethods($builder)
|
||||
{
|
||||
$queryClassName = $builder->getQueryClassName();
|
||||
$updateColumnConstant = $this->getColumnConstant('update_column', $builder);
|
||||
$createColumnConstant = $this->getColumnConstant('create_column', $builder);
|
||||
|
||||
return "
|
||||
/**
|
||||
* Filter by the latest updated
|
||||
*
|
||||
* @param int \$nbDays Maximum age of the latest update in days
|
||||
*
|
||||
* @return $queryClassName The current query, for fluid interface
|
||||
*/
|
||||
public function recentlyUpdated(\$nbDays = 7)
|
||||
{
|
||||
return \$this->addUsingAlias($updateColumnConstant, time() - \$nbDays * 24 * 60 * 60, Criteria::GREATER_EQUAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter by the latest created
|
||||
*
|
||||
* @param int \$nbDays Maximum age of in days
|
||||
*
|
||||
* @return $queryClassName The current query, for fluid interface
|
||||
*/
|
||||
public function recentlyCreated(\$nbDays = 7)
|
||||
{
|
||||
return \$this->addUsingAlias($createColumnConstant, time() - \$nbDays * 24 * 60 * 60, Criteria::GREATER_EQUAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Order by update date desc
|
||||
*
|
||||
* @return $queryClassName The current query, for fluid interface
|
||||
*/
|
||||
public function lastUpdatedFirst()
|
||||
{
|
||||
return \$this->addDescendingOrderByColumn($updateColumnConstant);
|
||||
}
|
||||
|
||||
/**
|
||||
* Order by update date asc
|
||||
*
|
||||
* @return $queryClassName The current query, for fluid interface
|
||||
*/
|
||||
public function firstUpdatedFirst()
|
||||
{
|
||||
return \$this->addAscendingOrderByColumn($updateColumnConstant);
|
||||
}
|
||||
|
||||
/**
|
||||
* Order by create date desc
|
||||
*
|
||||
* @return $queryClassName The current query, for fluid interface
|
||||
*/
|
||||
public function lastCreatedFirst()
|
||||
{
|
||||
return \$this->addDescendingOrderByColumn($createColumnConstant);
|
||||
}
|
||||
|
||||
/**
|
||||
* Order by create date asc
|
||||
*
|
||||
* @return $queryClassName The current query, for fluid interface
|
||||
*/
|
||||
public function firstCreatedFirst()
|
||||
{
|
||||
return \$this->addAscendingOrderByColumn($createColumnConstant);
|
||||
}
|
||||
";
|
||||
}
|
||||
}
|
||||
265
core/vendor/propel/propel/src/Propel/Generator/Behavior/Validate/ValidateBehavior.php
vendored
Normal file
265
core/vendor/propel/propel/src/Propel/Generator/Behavior/Validate/ValidateBehavior.php
vendored
Normal file
@@ -0,0 +1,265 @@
|
||||
<?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\Behavior\Validate;
|
||||
|
||||
use Propel\Generator\Exception\ConstraintNotFoundException;
|
||||
use Propel\Generator\Exception\InvalidArgumentException;
|
||||
use Propel\Generator\Model\Behavior;
|
||||
use Symfony\Component\Yaml\Parser;
|
||||
|
||||
/**
|
||||
* Validate a model object using Symfony2 Validator component
|
||||
*
|
||||
* @author Cristiano Cinotti
|
||||
*/
|
||||
class ValidateBehavior extends Behavior
|
||||
{
|
||||
/**
|
||||
* @param object $builder The current builder
|
||||
*/
|
||||
protected $builder;
|
||||
|
||||
/**
|
||||
* Add behavior methods to model class
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function objectMethods($builder)
|
||||
{
|
||||
$array = $this->getParameters();
|
||||
if (empty($array)) {
|
||||
throw new InvalidArgumentException('Please, define your rules for validation.');
|
||||
}
|
||||
$this->cleanupParameters();
|
||||
|
||||
$this->builder = $builder;
|
||||
$this->builder->declareClasses(
|
||||
'Symfony\\Component\\Validator\\Mapping\\ClassMetadata',
|
||||
'Symfony\\Component\\Validator\\Validator',
|
||||
'Symfony\\Component\\Validator\\DefaultTranslator',
|
||||
'Symfony\\Component\\Validator\\Mapping\\Loader\\StaticMethodLoader',
|
||||
'Symfony\\Component\\Validator\\ConstraintValidatorFactory',
|
||||
'Symfony\\Component\\Validator\\Mapping\\ClassMetadataFactory',
|
||||
'Symfony\\Component\\Validator\\ConstraintViolationList'
|
||||
);
|
||||
|
||||
$script = $this->addLoadValidatorMetadataMethod();
|
||||
$script .= $this->addValidateMethod();
|
||||
$script .= $this->addGetValidationFailuresMethod();
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add behavior attributes to model class
|
||||
*
|
||||
* @return string The code to be added to model class
|
||||
*/
|
||||
public function objectAttributes()
|
||||
{
|
||||
return $this->renderTemplate('objectAttributes');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parameters associated with a given column.
|
||||
* Useful for i18n behavior
|
||||
*
|
||||
* @param string The column name
|
||||
* @return array The array of parameters associated to given column
|
||||
*/
|
||||
public function getParametersFromColumnName($columnName = null)
|
||||
{
|
||||
$array = array();
|
||||
if (null !== $columnName) {
|
||||
$this->cleanupParameters();
|
||||
foreach ($this->getParameters() as $key => $parameter) {
|
||||
if ($parameter['column'] === $columnName) {
|
||||
$array[$key] = $parameter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove parameters associated with given column.
|
||||
* Useful for i18n behavior
|
||||
*
|
||||
* @param string The column name
|
||||
*/
|
||||
public function removeParametersFromColumnName($columnName = null)
|
||||
{
|
||||
if (null !== $columnName) {
|
||||
$newParams = array();
|
||||
$parameters = $this->getParameters();
|
||||
foreach ($parameters as $key => $parameter) {
|
||||
if ($parameter['column'] != $columnName) {
|
||||
$newParams[$key] = $parameter;
|
||||
}
|
||||
}
|
||||
|
||||
$this->setParameters($newParams);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a rule based on primary key type, if there aren't other parameters.
|
||||
* Useful when modify table (i18n behavior).
|
||||
* If all the rules have been removed, the behavior can't perform validation on related tables.
|
||||
* This method introduce a rule to avoid this.
|
||||
*/
|
||||
public function addRuleOnPk()
|
||||
{
|
||||
if (!count($this->getParameters())) {
|
||||
$pk = $this->getTable()->getPrimaryKey();
|
||||
$parameters = array('auto_rule' => array(
|
||||
'column' => $pk[0]->getName(),
|
||||
'validators' => 'Type',
|
||||
'options' => array(
|
||||
'type' => $pk[0]->getPhpType(),
|
||||
),
|
||||
));
|
||||
$this->setParameters($parameters);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge $paramArray array into parameters array.
|
||||
* This method avoid that there are rules with the same name, when adding parameters programmatically.
|
||||
* Useful for Concrete Inheritance behavior.
|
||||
*/
|
||||
public function mergeParameters(array $params = null)
|
||||
{
|
||||
if (null !== $params) {
|
||||
$parameters = $this->getParameters();
|
||||
$out = array();
|
||||
$i = 1;
|
||||
foreach ($parameters as $key => $parameter) {
|
||||
$out["rule$i"] = $parameter;
|
||||
$i++;
|
||||
}
|
||||
foreach ($params as $key => $param) {
|
||||
$out["rule$i"] = $param;
|
||||
$i++;
|
||||
}
|
||||
|
||||
$this->setParameters($out);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert those parameters, containing an array in YAML format
|
||||
* into a php array
|
||||
*/
|
||||
protected function cleanupParameters()
|
||||
{
|
||||
$parser = new Parser();
|
||||
$params = $this->getParameters();
|
||||
foreach ($params as $key => $value) {
|
||||
if (is_string($value)) {
|
||||
$params[$key] = $parser->parse($value);
|
||||
}
|
||||
}
|
||||
$this->setParameters($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add loadValidatorMetadata() method
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function addLoadValidatorMetadataMethod()
|
||||
{
|
||||
$params = $this->getParameters();
|
||||
$constraints = array();
|
||||
|
||||
foreach ($params as $key => $properties) {
|
||||
if (!isset($properties['column'])) {
|
||||
throw new InvalidArgumentException('Please, define the column to validate.');
|
||||
}
|
||||
|
||||
if (!isset($properties['validator'])) {
|
||||
throw new InvalidArgumentException('Please, define the validator constraint.');
|
||||
}
|
||||
|
||||
if (!class_exists("Symfony\\Component\\Validator\\Constraints\\".$properties['validator'], true)) {
|
||||
if (!class_exists("Propel\\Runtime\\Validator\\Constraints\\".$properties['validator'], true)) {
|
||||
throw new ConstraintNotFoundException('The constraint class '.$properties['validator'].' does not exist.');
|
||||
} else {
|
||||
$classConstraint = "Propel\\Runtime\\Validator\\Constraints\\".$properties['validator'];
|
||||
}
|
||||
} else {
|
||||
$classConstraint = "Symfony\\Component\\Validator\\Constraints\\".$properties['validator'];
|
||||
}
|
||||
|
||||
if (isset($properties['options'])) {
|
||||
if (!is_array($properties['options'])) {
|
||||
throw new InvalidArgumentException('The options value, in <parameter> tag must be an array');
|
||||
}
|
||||
|
||||
$opt = var_export($properties['options'], true);
|
||||
$opt = str_replace("\n", '', $opt);
|
||||
$opt = str_replace(' ', '', $opt);
|
||||
$properties['options'] = $opt;
|
||||
}
|
||||
|
||||
$constraints[] = $properties;
|
||||
$this->builder->declareClass($classConstraint);
|
||||
}
|
||||
|
||||
return $this->renderTemplate('objectLoadValidatorMetadata', array('constraints' => $constraints));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the validate() method.
|
||||
* @return string The code to be added to model class
|
||||
*/
|
||||
protected function addValidateMethod()
|
||||
{
|
||||
$table = $this->getTable();
|
||||
$foreignKeys = $table->getForeignKeys();
|
||||
$hasForeignKeys = (count($foreignKeys) != 0);
|
||||
$aVarNames = array();
|
||||
$refFkVarNames = array();
|
||||
$collVarNames = array();
|
||||
|
||||
if ($hasForeignKeys) {
|
||||
foreach ($foreignKeys as $fk) {
|
||||
$aVarNames[] = $this->builder->getFKVarName($fk);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($table->getReferrers() as $refFK) {
|
||||
if ($refFK->isLocalPrimaryKey()) {
|
||||
$refFkVarNames[] = $this->builder->getPKRefFKVarName($refFK);
|
||||
} else {
|
||||
$collVarNames[] = $this->builder->getRefFKCollVarName($refFK);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->renderTemplate('objectValidate', array(
|
||||
'hasForeignKeys' => $hasForeignKeys,
|
||||
'aVarNames' => $aVarNames,
|
||||
'refFkVarNames' => $refFkVarNames,
|
||||
'collVarNames' => $collVarNames
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the getValidationFailures() method.
|
||||
*/
|
||||
protected function addGetValidationFailuresMethod()
|
||||
{
|
||||
return $this->renderTemplate('objectGetValidationFailures');
|
||||
}
|
||||
|
||||
}
|
||||
15
core/vendor/propel/propel/src/Propel/Generator/Behavior/Validate/templates/objectAttributes.php
vendored
Normal file
15
core/vendor/propel/propel/src/Propel/Generator/Behavior/Validate/templates/objectAttributes.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
/**
|
||||
* Flag to prevent endless validation loop, if this object is referenced
|
||||
* by another object which falls in this transaction.
|
||||
* @var boolean
|
||||
*/
|
||||
protected $alreadyInValidation = false;
|
||||
|
||||
/**
|
||||
* ConstraintViolationList object
|
||||
*
|
||||
* @see http://api.symfony.com/2.0/Symfony/Component/Validator/ConstraintViolationList.html
|
||||
* @var ConstraintViolationList
|
||||
*/
|
||||
protected $validationFailures;
|
||||
@@ -0,0 +1,12 @@
|
||||
|
||||
/**
|
||||
* Gets any ConstraintViolation objects that resulted from last call to validate().
|
||||
*
|
||||
*
|
||||
* @return object ConstraintViolationList
|
||||
* @see validate()
|
||||
*/
|
||||
public function getValidationFailures()
|
||||
{
|
||||
return $this->validationFailures;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
/**
|
||||
* Configure validators constraints. The Validator object uses this method
|
||||
* to perform object validation.
|
||||
*
|
||||
* @param ClassMetadata $metadata
|
||||
*/
|
||||
static public function loadValidatorMetadata(ClassMetadata $metadata)
|
||||
{
|
||||
<?php foreach($constraints as $constraint) : ?>
|
||||
$metadata->addPropertyConstraint('<?php echo $constraint['column']; ?>', new <?php echo $constraint['validator']; ?>(<?php echo((isset($constraint['options'])) ? $constraint['options'] : ''); ?>));
|
||||
<?php endforeach; ?>
|
||||
}
|
||||
61
core/vendor/propel/propel/src/Propel/Generator/Behavior/Validate/templates/objectValidate.php
vendored
Normal file
61
core/vendor/propel/propel/src/Propel/Generator/Behavior/Validate/templates/objectValidate.php
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
|
||||
/**
|
||||
* Validates the object and all objects related to this table.
|
||||
*
|
||||
* @see getValidationFailures()
|
||||
* @param object $validator A Validator class instance
|
||||
* @return boolean Whether all objects pass validation.
|
||||
*/
|
||||
public function validate(Validator $validator = null)
|
||||
{
|
||||
if (null === $validator) {
|
||||
$validator = new Validator(new ClassMetadataFactory(new StaticMethodLoader()), new ConstraintValidatorFactory(), new DefaultTranslator());
|
||||
}
|
||||
|
||||
$failureMap = new ConstraintViolationList();
|
||||
|
||||
if (!$this->alreadyInValidation) {
|
||||
$this->alreadyInValidation = true;
|
||||
$retval = null;
|
||||
|
||||
<?php if ($hasForeignKeys) : ?>
|
||||
// We call the validate method on the following object(s) if they
|
||||
// were passed to this object by their corresponding set
|
||||
// method. This object relates to these object(s) by a
|
||||
// foreign key reference.
|
||||
|
||||
<?php foreach($aVarNames as $aVarName) : ?>
|
||||
// If validate() method exists, the validate-behavior is configured for related object
|
||||
if (method_exists($this-><?php echo $aVarName; ?>, 'validate')) {
|
||||
if (!$this-><?php echo $aVarName; ?>->validate($validator)) {
|
||||
$failureMap->addAll($this-><?php echo $aVarName; ?>->getValidationFailures());
|
||||
}
|
||||
}
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
$retval = $validator->validate($this);
|
||||
if (count($retval) > 0) {
|
||||
$failureMap->addAll($retval);
|
||||
}
|
||||
|
||||
<?php foreach($collVarNames as $collVarName) : ?>
|
||||
if (null !== $this-><?php echo $collVarName; ?>) {
|
||||
foreach ($this-><?php echo $collVarName; ?> as $referrerFK) {
|
||||
if (method_exists($referrerFK, 'validate')) {
|
||||
if (!$referrerFK->validate($validator)) {
|
||||
$failureMap->addAll($referrerFK->getValidationFailures());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
<?php endforeach; ?>
|
||||
|
||||
$this->alreadyInValidation = false;
|
||||
}
|
||||
|
||||
$this->validationFailures = $failureMap;
|
||||
|
||||
return (Boolean) (!(count($this->validationFailures) > 0));
|
||||
|
||||
}
|
||||
264
core/vendor/propel/propel/src/Propel/Generator/Behavior/Versionable/VersionableBehavior.php
vendored
Normal file
264
core/vendor/propel/propel/src/Propel/Generator/Behavior/Versionable/VersionableBehavior.php
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
<?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\Behavior\Versionable;
|
||||
|
||||
use Propel\Generator\Model\Behavior;
|
||||
use Propel\Generator\Model\ForeignKey;
|
||||
|
||||
/**
|
||||
* Keeps tracks of all the modifications in an ActiveRecord object
|
||||
*
|
||||
* @author Francois Zaninotto
|
||||
*/
|
||||
class VersionableBehavior extends Behavior
|
||||
{
|
||||
// default parameters value
|
||||
protected $parameters = array(
|
||||
'version_column' => 'version',
|
||||
'version_table' => '',
|
||||
'log_created_at' => 'false',
|
||||
'log_created_by' => 'false',
|
||||
'log_comment' => 'false',
|
||||
'version_created_at_column' => 'version_created_at',
|
||||
'version_created_by_column' => 'version_created_by',
|
||||
'version_comment_column' => 'version_comment'
|
||||
);
|
||||
|
||||
protected $versionTable;
|
||||
|
||||
protected $objectBuilderModifier;
|
||||
|
||||
protected $queryBuilderModifier;
|
||||
|
||||
protected $tableModificationOrder = 80;
|
||||
|
||||
public function modifyDatabase()
|
||||
{
|
||||
foreach ($this->getDatabase()->getTables() as $table) {
|
||||
if ($table->hasBehavior($this->getName())) {
|
||||
// don't add the same behavior twice
|
||||
continue;
|
||||
}
|
||||
if (property_exists($table, 'isVersionTable')) {
|
||||
// don't add the behavior to version tables
|
||||
continue;
|
||||
}
|
||||
$b = clone $this;
|
||||
$table->addBehavior($b);
|
||||
}
|
||||
}
|
||||
|
||||
public function modifyTable()
|
||||
{
|
||||
$this->addVersionColumn();
|
||||
$this->addLogColumns();
|
||||
$this->addVersionTable();
|
||||
$this->addForeignKeyVersionColumns();
|
||||
}
|
||||
|
||||
protected function addVersionColumn()
|
||||
{
|
||||
$table = $this->getTable();
|
||||
// add the version column
|
||||
if (!$table->hasColumn($this->getParameter('version_column'))) {
|
||||
$table->addColumn(array(
|
||||
'name' => $this->getParameter('version_column'),
|
||||
'type' => 'INTEGER',
|
||||
'default' => 0
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
protected function addLogColumns()
|
||||
{
|
||||
$table = $this->getTable();
|
||||
if ('true' === $this->getParameter('log_created_at') && !$table->hasColumn($this->getParameter('version_created_at_column'))) {
|
||||
$table->addColumn(array(
|
||||
'name' => $this->getParameter('version_created_at_column'),
|
||||
'type' => 'TIMESTAMP'
|
||||
));
|
||||
}
|
||||
if ('true' === $this->getParameter('log_created_by') && !$table->hasColumn($this->getParameter('version_created_by_column'))) {
|
||||
$table->addColumn(array(
|
||||
'name' => $this->getParameter('version_created_by_column'),
|
||||
'type' => 'VARCHAR',
|
||||
'size' => 100
|
||||
));
|
||||
}
|
||||
if ('true' === $this->getParameter('log_comment') && !$table->hasColumn($this->getParameter('version_comment_column'))) {
|
||||
$table->addColumn(array(
|
||||
'name' => $this->getParameter('version_comment_column'),
|
||||
'type' => 'VARCHAR',
|
||||
'size' => 255
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
protected function addVersionTable()
|
||||
{
|
||||
$table = $this->getTable();
|
||||
$database = $table->getDatabase();
|
||||
$versionTableName = $this->getParameter('version_table') ? $this->getParameter('version_table') : ($table->getName() . '_version');
|
||||
if (!$database->hasTable($versionTableName)) {
|
||||
// create the version table
|
||||
$versionTable = $database->addTable(array(
|
||||
'name' => $versionTableName,
|
||||
'phpName' => $this->getVersionTablePhpName(),
|
||||
'package' => $table->getPackage(),
|
||||
'schema' => $table->getSchema(),
|
||||
'namespace' => $table->getNamespace() ? '\\' . $table->getNamespace() : null,
|
||||
'skipSql' => $table->isSkipSql()
|
||||
));
|
||||
$versionTable->isVersionTable = true;
|
||||
// every behavior adding a table should re-execute database behaviors
|
||||
foreach ($database->getBehaviors() as $behavior) {
|
||||
$behavior->modifyDatabase();
|
||||
}
|
||||
// copy all the columns
|
||||
foreach ($table->getColumns() as $column) {
|
||||
$columnInVersionTable = clone $column;
|
||||
$columnInVersionTable->clearInheritanceList();
|
||||
if ($columnInVersionTable->hasReferrers()) {
|
||||
$columnInVersionTable->clearReferrers();
|
||||
}
|
||||
if ($columnInVersionTable->isAutoincrement()) {
|
||||
$columnInVersionTable->setAutoIncrement(false);
|
||||
}
|
||||
$versionTable->addColumn($columnInVersionTable);
|
||||
}
|
||||
// create the foreign key
|
||||
$fk = new ForeignKey();
|
||||
$fk->setForeignTableCommonName($table->getCommonName());
|
||||
$fk->setForeignSchemaName($table->getSchema());
|
||||
$fk->setOnDelete('CASCADE');
|
||||
$fk->setOnUpdate(null);
|
||||
$tablePKs = $table->getPrimaryKey();
|
||||
foreach ($versionTable->getPrimaryKey() as $key => $column) {
|
||||
$fk->addReference($column, $tablePKs[$key]);
|
||||
}
|
||||
$versionTable->addForeignKey($fk);
|
||||
|
||||
// add the version column to the primary key
|
||||
$versionColumn = $versionTable->getColumn($this->getParameter('version_column'));
|
||||
$versionColumn->setNotNull(true);
|
||||
$versionColumn->setPrimaryKey(true);
|
||||
$this->versionTable = $versionTable;
|
||||
} else {
|
||||
$this->versionTable = $database->getTable($versionTableName);
|
||||
}
|
||||
}
|
||||
|
||||
public function addForeignKeyVersionColumns()
|
||||
{
|
||||
$versionTable = $this->versionTable;
|
||||
foreach ($this->getVersionableFks() as $fk) {
|
||||
$fkVersionColumnName = $fk->getLocalColumnName() . '_version';
|
||||
if (!$versionTable->hasColumn($fkVersionColumnName)) {
|
||||
$versionTable->addColumn(array(
|
||||
'name' => $fkVersionColumnName,
|
||||
'type' => 'INTEGER',
|
||||
'default' => 0
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->getVersionableReferrers() as $fk) {
|
||||
$fkTableName = $fk->getTable()->getName();
|
||||
$fkIdsColumnName = $fkTableName . '_ids';
|
||||
if (!$versionTable->hasColumn($fkIdsColumnName)) {
|
||||
$versionTable->addColumn(array(
|
||||
'name' => $fkIdsColumnName,
|
||||
'type' => 'ARRAY'
|
||||
));
|
||||
}
|
||||
|
||||
$fkVersionsColumnName = $fkTableName . '_versions';
|
||||
if (!$versionTable->hasColumn($fkVersionsColumnName)) {
|
||||
$versionTable->addColumn(array(
|
||||
'name' => $fkVersionsColumnName,
|
||||
'type' => 'ARRAY'
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getVersionTable()
|
||||
{
|
||||
return $this->versionTable;
|
||||
}
|
||||
|
||||
public function getVersionTablePhpName()
|
||||
{
|
||||
return $this->getTable()->getPhpName() . 'Version';
|
||||
}
|
||||
|
||||
public function getVersionableFks()
|
||||
{
|
||||
$versionableFKs = array();
|
||||
if ($fks = $this->getTable()->getForeignKeys()) {
|
||||
foreach ($fks as $fk) {
|
||||
if ($fk->getForeignTable()->hasBehavior($this->getName()) && ! $fk->isComposite()) {
|
||||
$versionableFKs []= $fk;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $versionableFKs;
|
||||
}
|
||||
|
||||
public function getVersionableReferrers()
|
||||
{
|
||||
$versionableReferrers = array();
|
||||
if ($fks = $this->getTable()->getReferrers()) {
|
||||
foreach ($fks as $fk) {
|
||||
if ($fk->getTable()->hasBehavior($this->getName()) && ! $fk->isComposite()) {
|
||||
$versionableReferrers []= $fk;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $versionableReferrers;
|
||||
}
|
||||
|
||||
public function getReferrerIdsColumn(ForeignKey $fk)
|
||||
{
|
||||
$fkTableName = $fk->getTable()->getName();
|
||||
$fkIdsColumnName = $fkTableName . '_ids';
|
||||
|
||||
return $this->versionTable->getColumn($fkIdsColumnName);
|
||||
}
|
||||
|
||||
public function getReferrerVersionsColumn(ForeignKey $fk)
|
||||
{
|
||||
$fkTableName = $fk->getTable()->getName();
|
||||
$fkIdsColumnName = $fkTableName . '_versions';
|
||||
|
||||
return $this->versionTable->getColumn($fkIdsColumnName);
|
||||
}
|
||||
|
||||
public function getObjectBuilderModifier()
|
||||
{
|
||||
if (null === $this->objectBuilderModifier) {
|
||||
$this->objectBuilderModifier = new VersionableBehaviorObjectBuilderModifier($this);
|
||||
}
|
||||
|
||||
return $this->objectBuilderModifier;
|
||||
}
|
||||
|
||||
public function getQueryBuilderModifier()
|
||||
{
|
||||
if (null === $this->queryBuilderModifier) {
|
||||
$this->queryBuilderModifier = new VersionableBehaviorQueryBuilderModifier($this);
|
||||
}
|
||||
|
||||
return $this->queryBuilderModifier;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,694 @@
|
||||
<?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\Behavior\Versionable;
|
||||
|
||||
/**
|
||||
* Behavior to add versionable columns and abilities
|
||||
*
|
||||
* @author François Zaninotto
|
||||
*/
|
||||
class VersionableBehaviorObjectBuilderModifier
|
||||
{
|
||||
protected $behavior;
|
||||
protected $table;
|
||||
protected $builder;
|
||||
protected $objectClassName;
|
||||
|
||||
public function __construct($behavior)
|
||||
{
|
||||
$this->behavior = $behavior;
|
||||
$this->table = $behavior->getTable();
|
||||
}
|
||||
|
||||
protected function getParameter($key)
|
||||
{
|
||||
return $this->behavior->getParameter($key);
|
||||
}
|
||||
|
||||
protected function getColumnAttribute($name = 'version_column')
|
||||
{
|
||||
return strtolower($this->behavior->getColumnForParameter($name)->getName());
|
||||
}
|
||||
|
||||
protected function getColumnPhpName($name = 'version_column')
|
||||
{
|
||||
return $this->behavior->getColumnForParameter($name)->getPhpName();
|
||||
}
|
||||
|
||||
protected function getVersionQueryClassName()
|
||||
{
|
||||
return $this->builder->getClassNameFromBuilder($this->builder->getNewStubQueryBuilder($this->behavior->getVersionTable()));
|
||||
}
|
||||
|
||||
protected function getActiveRecordClassName()
|
||||
{
|
||||
return $this->builder->getObjectClassName();
|
||||
}
|
||||
|
||||
protected function setBuilder($builder)
|
||||
{
|
||||
$this->builder = $builder;
|
||||
$this->objectClassName = $builder->getObjectClassName();
|
||||
$this->queryClassName = $builder->getQueryClassName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the getter of the column of the behavior
|
||||
*
|
||||
* @return string The related getter, e.g. 'getVersion'
|
||||
*/
|
||||
protected function getColumnGetter($name = 'version_column')
|
||||
{
|
||||
return 'get' . $this->getColumnPhpName($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the setter of the column of the behavior
|
||||
*
|
||||
* @return string The related setter, e.g. 'setVersion'
|
||||
*/
|
||||
protected function getColumnSetter($name = 'version_column')
|
||||
{
|
||||
return 'set' . $this->getColumnPhpName($name);
|
||||
}
|
||||
|
||||
public function preSave($builder)
|
||||
{
|
||||
$script = "if (\$this->isVersioningNecessary()) {
|
||||
\$this->set{$this->getColumnPhpName()}(\$this->isNew() ? 1 : \$this->getLastVersionNumber(\$con) + 1);";
|
||||
if ($this->behavior->getParameter('log_created_at') == 'true') {
|
||||
$col = $this->behavior->getTable()->getColumn($this->getParameter('version_created_at_column'));
|
||||
$script .= "
|
||||
if (!\$this->isColumnModified({$this->builder->getColumnConstant($col)})) {
|
||||
\$this->{$this->getColumnSetter('version_created_at_column')}(time());
|
||||
}";
|
||||
}
|
||||
$script .= "
|
||||
\$createVersion = true; // for postSave hook
|
||||
}";
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
public function postSave($builder)
|
||||
{
|
||||
return "if (isset(\$createVersion)) {
|
||||
\$this->addVersion(\$con);
|
||||
}";
|
||||
}
|
||||
|
||||
public function postDelete($builder)
|
||||
{
|
||||
$this->builder = $builder;
|
||||
if (!$builder->getPlatform()->supportsNativeDeleteTrigger() && !$builder->getBuildProperty('emulateForeignKeyConstraints')) {
|
||||
$script = "// emulate delete cascade
|
||||
{$this->getVersionQueryClassName()}::create()
|
||||
->filterBy{$this->table->getPhpName()}(\$this)
|
||||
->delete(\$con);";
|
||||
|
||||
return $script;
|
||||
}
|
||||
}
|
||||
|
||||
public function objectAttributes($builder)
|
||||
{
|
||||
$script = '';
|
||||
|
||||
$this->addEnforceVersionAttribute($script);
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
protected function addEnforceVersionAttribute(&$script)
|
||||
{
|
||||
$script .= "
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected \$enforceVersion = false;
|
||||
";
|
||||
}
|
||||
|
||||
public function objectMethods($builder)
|
||||
{
|
||||
$this->setBuilder($builder);
|
||||
$script = '';
|
||||
if ('version' !== $this->getParameter('version_column')) {
|
||||
$this->addVersionSetter($script);
|
||||
$this->addVersionGetter($script);
|
||||
}
|
||||
$this->addEnforceVersioning($script);
|
||||
$this->addIsVersioningNecessary($script);
|
||||
$this->addAddVersion($script);
|
||||
$this->addToVersion($script);
|
||||
$this->addPopulateFromVersion($script);
|
||||
$this->addGetLastVersionNumber($script);
|
||||
$this->addIsLastVersion($script);
|
||||
$this->addGetOneVersion($script);
|
||||
$this->addGetAllVersions($script);
|
||||
$this->addCompareVersion($script);
|
||||
$this->addCompareVersions($script);
|
||||
$this->addComputeDiff($script);
|
||||
$this->addGetLastVersions($script);
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
protected function addVersionSetter(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Wrap the setter for version value
|
||||
*
|
||||
* @param string
|
||||
* @return " . $this->table->getPhpName() . "
|
||||
*/
|
||||
public function setVersion(\$v)
|
||||
{
|
||||
return \$this->" . $this->getColumnSetter() . "(\$v);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addVersionGetter(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Wrap the getter for version value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getVersion()
|
||||
{
|
||||
return \$this->" . $this->getColumnGetter() . "();
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addEnforceVersioning(&$script)
|
||||
{
|
||||
$objectClass = $this->builder->getStubObjectBuilder()->getClassname();
|
||||
$script .= "
|
||||
/**
|
||||
* Enforce a new Version of this object upon next save.
|
||||
*
|
||||
* @return {$objectClass}
|
||||
*/
|
||||
public function enforceVersioning()
|
||||
{
|
||||
\$this->enforceVersion = true;
|
||||
|
||||
return \$this;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addIsVersioningNecessary(&$script)
|
||||
{
|
||||
$queryClassName = $this->builder->getQueryClassName();
|
||||
|
||||
$script .= "
|
||||
/**
|
||||
* Checks whether the current state must be recorded as a version
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isVersioningNecessary(\$con = null)
|
||||
{
|
||||
if (\$this->alreadyInSave) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (\$this->enforceVersion) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ({$queryClassName}::isVersioningEnabled() && (\$this->isNew() || \$this->isModified()) || \$this->isDeleted()) {
|
||||
return true;
|
||||
}";
|
||||
$plural = false;
|
||||
foreach ($this->behavior->getVersionableFks() as $fk) {
|
||||
$fkGetter = $this->builder->getFKPhpNameAffix($fk, $plural);
|
||||
$script .= "
|
||||
if (null !== (\$object = \$this->get{$fkGetter}(\$con)) && \$object->isVersioningNecessary(\$con)) {
|
||||
return true;
|
||||
}
|
||||
";
|
||||
}
|
||||
$plural = true;
|
||||
foreach ($this->behavior->getVersionableReferrers() as $fk) {
|
||||
$fkGetter = $this->builder->getRefFKPhpNameAffix($fk, $plural);
|
||||
$script .= "
|
||||
// to avoid infinite loops, emulate in save
|
||||
\$this->alreadyInSave = true;
|
||||
foreach (\$this->get{$fkGetter}(null, \$con) as \$relatedObject) {
|
||||
if (\$relatedObject->isVersioningNecessary(\$con)) {
|
||||
\$this->alreadyInSave = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
\$this->alreadyInSave = false;
|
||||
";
|
||||
}
|
||||
$script .= "
|
||||
|
||||
return false;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addAddVersion(&$script)
|
||||
{
|
||||
$versionTable = $this->behavior->getVersionTable();
|
||||
$versionARClassName = $this->builder->getClassNameFromBuilder($this->builder->getNewStubObjectBuilder($versionTable));
|
||||
|
||||
$script .= "
|
||||
/**
|
||||
* Creates a version of the current object and saves it.
|
||||
*
|
||||
* @param ConnectionInterface \$con the connection to use
|
||||
*
|
||||
* @return {$versionARClassName} A version object
|
||||
*/
|
||||
public function addVersion(\$con = null)
|
||||
{
|
||||
\$this->enforceVersion = false;
|
||||
|
||||
\$version = new {$versionARClassName}();";
|
||||
foreach ($this->table->getColumns() as $col) {
|
||||
$script .= "
|
||||
\$version->set" . $col->getPhpName() . "(\$this->get" . $col->getPhpName() . "());";
|
||||
}
|
||||
$script .= "
|
||||
\$version->set{$this->table->getPhpName()}(\$this);";
|
||||
$plural = false;
|
||||
foreach ($this->behavior->getVersionableFks() as $fk) {
|
||||
$fkGetter = $this->builder->getFKPhpNameAffix($fk, $plural);
|
||||
$fkVersionColumnName = $fk->getLocalColumnName() . '_version';
|
||||
$fkVersionColumnPhpName = $versionTable->getColumn($fkVersionColumnName)->getPhpName();
|
||||
$script .= "
|
||||
if ((\$related = \$this->get{$fkGetter}(\$con)) && \$related->getVersion()) {
|
||||
\$version->set{$fkVersionColumnPhpName}(\$related->getVersion());
|
||||
}";
|
||||
}
|
||||
$plural = true;
|
||||
foreach ($this->behavior->getVersionableReferrers() as $fk) {
|
||||
$fkGetter = $this->builder->getRefFKPhpNameAffix($fk, $plural);
|
||||
$idsColumn = $this->behavior->getReferrerIdsColumn($fk);
|
||||
$versionsColumn = $this->behavior->getReferrerVersionsColumn($fk);
|
||||
$script .= "
|
||||
if (\$relateds = \$this->get{$fkGetter}(\$con)->toKeyValue('{$fk->getForeignColumn()->getPhpName()}', 'Version')) {
|
||||
\$version->set{$idsColumn->getPhpName()}(array_keys(\$relateds));
|
||||
\$version->set{$versionsColumn->getPhpName()}(array_values(\$relateds));
|
||||
}";
|
||||
}
|
||||
$script .= "
|
||||
\$version->save(\$con);
|
||||
|
||||
return \$version;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addToVersion(&$script)
|
||||
{
|
||||
$ARclassName = $this->getActiveRecordClassName();
|
||||
$script .= "
|
||||
/**
|
||||
* Sets the properties of the current object to the value they had at a specific version
|
||||
*
|
||||
* @param integer \$versionNumber The version number to read
|
||||
* @param ConnectionInterface \$con The connection to use
|
||||
*
|
||||
* @return {$ARclassName} The current object (for fluent API support)
|
||||
*/
|
||||
public function toVersion(\$versionNumber, \$con = null)
|
||||
{
|
||||
\$version = \$this->getOneVersion(\$versionNumber, \$con);
|
||||
if (!\$version) {
|
||||
throw new PropelException(sprintf('No {$ARclassName} object found with version %d', \$version));
|
||||
}
|
||||
\$this->populateFromVersion(\$version, \$con);
|
||||
|
||||
return \$this;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addPopulateFromVersion(&$script)
|
||||
{
|
||||
$ARclassName = $this->getActiveRecordClassName();
|
||||
$versionTable = $this->behavior->getVersionTable();
|
||||
$versionColumnName = $versionTable->getColumn($this->behavior->getParameter('version_column'))->getPhpName();
|
||||
$versionARClassName = $this->builder->getClassNameFromBuilder($this->builder->getNewStubObjectBuilder($versionTable));
|
||||
$tablePKs = $this->table->getPrimaryKey();
|
||||
$primaryKeyName = $tablePKs[0]->getPhpName();
|
||||
$script .= "
|
||||
/**
|
||||
* Sets the properties of the current object to the value they had at a specific version
|
||||
*
|
||||
* @param {$versionARClassName} \$version The version object to use
|
||||
* @param ConnectionInterface \$con the connection to use
|
||||
* @param array \$loadedObjects objects that been loaded in a chain of populateFromVersion calls on referrer or fk objects.
|
||||
*
|
||||
* @return {$ARclassName} The current object (for fluent API support)
|
||||
*/
|
||||
public function populateFromVersion(\$version, \$con = null, &\$loadedObjects = array())
|
||||
{";
|
||||
$script .= "
|
||||
\$loadedObjects['{$ARclassName}'][\$version->get{$primaryKeyName}()][\$version->get{$versionColumnName}()] = \$this;";
|
||||
|
||||
foreach ($this->table->getColumns() as $col) {
|
||||
$script .= "
|
||||
\$this->set" . $col->getPhpName() . "(\$version->get" . $col->getPhpName() . "());";
|
||||
}
|
||||
$plural = false;
|
||||
foreach ($this->behavior->getVersionableFks() as $fk) {
|
||||
$foreignTable = $fk->getForeignTable();
|
||||
$foreignVersionTable = $fk->getForeignTable()->getBehavior($this->behavior->getName())->getVersionTable();
|
||||
$relatedClassName = $this->builder->getClassNameFromBuilder($this->builder->getNewStubObjectBuilder($foreignTable));
|
||||
$relatedVersionQueryClassName = $this->builder->getClassNameFromBuilder($this->builder->getNewStubQueryBuilder($foreignVersionTable));
|
||||
$fkColumnName = $fk->getLocalColumnName();
|
||||
$fkColumnPhpName = $fk->getLocalColumn()->getPhpName();
|
||||
$fkVersionColumnPhpName = $versionTable->getColumn($fkColumnName . '_version')->getPhpName();
|
||||
$fkPhpname = $this->builder->getFKPhpNameAffix($fk, $plural);
|
||||
// FIXME: breaks lazy-loading
|
||||
$script .= "
|
||||
if (\$fkValue = \$version->get{$fkColumnPhpName}()) {
|
||||
if (isset(\$loadedObjects['{$relatedClassName}']) && isset(\$loadedObjects['{$relatedClassName}'][\$fkValue]) && isset(\$loadedObjects['{$relatedClassName}'][\$fkValue][\$version->get{$fkVersionColumnPhpName}()])) {
|
||||
\$related = \$loadedObjects['{$relatedClassName}'][\$fkValue][\$version->get{$fkVersionColumnPhpName}()];
|
||||
} else {
|
||||
\$related = new {$relatedClassName}();
|
||||
\$relatedVersion = {$relatedVersionQueryClassName}::create()
|
||||
->filterBy{$fk->getForeignColumn()->getPhpName()}(\$fkValue)
|
||||
->filterByVersion(\$version->get{$fkVersionColumnPhpName}())
|
||||
->findOne(\$con);
|
||||
\$related->populateFromVersion(\$relatedVersion, \$con, \$loadedObjects);
|
||||
\$related->setNew(false);
|
||||
}
|
||||
\$this->set{$fkPhpname}(\$related);
|
||||
}";
|
||||
}
|
||||
$plural = true;
|
||||
foreach ($this->behavior->getVersionableReferrers() as $fk) {
|
||||
$fkPhpNames = $this->builder->getRefFKPhpNameAffix($fk, $plural);
|
||||
$plural = false;
|
||||
$fkPhpName = $this->builder->getRefFKPhpNameAffix($fk, $plural);
|
||||
$foreignTable = $fk->getTable();
|
||||
$foreignBehavior = $foreignTable->getBehavior($this->behavior->getName());
|
||||
$foreignVersionTable = $foreignBehavior->getVersionTable();
|
||||
$fkColumnIds = $this->behavior->getReferrerIdsColumn($fk);
|
||||
$fkColumnVersions = $this->behavior->getReferrerVersionsColumn($fk);
|
||||
$relatedVersionQueryClassName = $this->builder->getClassNameFromBuilder($this->builder->getNewStubQueryBuilder($foreignVersionTable));
|
||||
$relatedVersionTableMapClassName = $this->builder->getClassNameFromBuilder($this->builder->getNewTableMapBuilder($foreignVersionTable));
|
||||
$relatedClassName = $this->builder->getClassNameFromBuilder($this->builder->getNewStubObjectBuilder($foreignTable));
|
||||
$fkColumn = $fk->getForeignColumn();
|
||||
$fkVersionColumn = $foreignVersionTable->getColumn($this->behavior->getParameter('version_column'));
|
||||
|
||||
$script .= "
|
||||
if (\$fkValues = \$version->get{$fkColumnIds->getPhpName()}()) {
|
||||
\$this->clear{$fkPhpNames}();
|
||||
\$fkVersions = \$version->get{$fkColumnVersions->getPhpName()}();
|
||||
\$query = {$relatedVersionQueryClassName}::create();
|
||||
foreach (\$fkValues as \$key => \$value) {
|
||||
\$c1 = \$query->getNewCriterion({$this->builder->getColumnConstant($fkColumn, $relatedVersionTableMapClassName)}, \$value);
|
||||
\$c2 = \$query->getNewCriterion({$this->builder->getColumnConstant($fkVersionColumn, $relatedVersionTableMapClassName)}, \$fkVersions[\$key]);
|
||||
\$c1->addAnd(\$c2);
|
||||
\$query->addOr(\$c1);
|
||||
}
|
||||
foreach (\$query->find(\$con) as \$relatedVersion) {
|
||||
if (isset(\$loadedObjects['{$relatedClassName}']) && isset(\$loadedObjects['{$relatedClassName}'][\$relatedVersion->get{$fkColumn->getPhpName()}()]) && isset(\$loadedObjects['{$relatedClassName}'][\$relatedVersion->get{$fkColumn->getPhpName()}()][\$relatedVersion->get{$fkVersionColumn->getPhpName()}()])) {
|
||||
\$related = \$loadedObjects['{$relatedClassName}'][\$relatedVersion->get{$fkColumn->getPhpName()}()][\$relatedVersion->get{$fkVersionColumn->getPhpName()}()];
|
||||
} else {
|
||||
\$related = new {$relatedClassName}();
|
||||
\$related->populateFromVersion(\$relatedVersion, \$con, \$loadedObjects);
|
||||
\$related->setNew(false);
|
||||
}
|
||||
\$this->add{$fkPhpName}(\$related);
|
||||
\$this->coll{$fkPhpNames}Partial = false;
|
||||
}
|
||||
}";
|
||||
}
|
||||
$script .= "
|
||||
|
||||
return \$this;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addGetLastVersionNumber(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Gets the latest persisted version number for the current object
|
||||
*
|
||||
* @param ConnectionInterface \$con the connection to use
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getLastVersionNumber(\$con = null)
|
||||
{
|
||||
\$v = {$this->getVersionQueryClassName()}::create()
|
||||
->filterBy{$this->table->getPhpName()}(\$this)
|
||||
->orderBy{$this->getColumnPhpName()}('desc')
|
||||
->findOne(\$con);
|
||||
if (!\$v) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return \$v->get{$this->getColumnPhpName()}();
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addIsLastVersion(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Checks whether the current object is the latest one
|
||||
*
|
||||
* @param ConnectionInterface \$con the connection to use
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public function isLastVersion(\$con = null)
|
||||
{
|
||||
return \$this->getLastVersionNumber(\$con) == \$this->getVersion();
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addGetOneVersion(&$script)
|
||||
{
|
||||
$versionARClassName = $this->builder->getClassNameFromBuilder($this->builder->getNewStubObjectBuilder($this->behavior->getVersionTable()));
|
||||
$script .= "
|
||||
/**
|
||||
* Retrieves a version object for this entity and a version number
|
||||
*
|
||||
* @param integer \$versionNumber The version number to read
|
||||
* @param ConnectionInterface \$con the connection to use
|
||||
*
|
||||
* @return {$versionARClassName} A version object
|
||||
*/
|
||||
public function getOneVersion(\$versionNumber, \$con = null)
|
||||
{
|
||||
return {$this->getVersionQueryClassName()}::create()
|
||||
->filterBy{$this->table->getPhpName()}(\$this)
|
||||
->filterBy{$this->getColumnPhpName()}(\$versionNumber)
|
||||
->findOne(\$con);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addGetAllVersions(&$script)
|
||||
{
|
||||
$versionTable = $this->behavior->getVersionTable();
|
||||
$versionARClassName = $this->builder->getClassNameFromBuilder($this->builder->getNewStubObjectBuilder($versionTable));
|
||||
//this force the use statement for VersionTableMap
|
||||
$this->builder->getClassNameFromBuilder($this->builder->getNewTableMapBuilder($versionTable));
|
||||
$versionForeignColumn = $versionTable->getColumn($this->behavior->getParameter('version_column'));
|
||||
$fks = $versionTable->getForeignKeysReferencingTable($this->table->getName());
|
||||
$relCol = $this->builder->getRefFKPhpNameAffix($fks[0], true);
|
||||
$script .= "
|
||||
/**
|
||||
* Gets all the versions of this object, in incremental order
|
||||
*
|
||||
* @param ConnectionInterface \$con the connection to use
|
||||
*
|
||||
* @return ObjectCollection A list of {$versionARClassName} objects
|
||||
*/
|
||||
public function getAllVersions(\$con = null)
|
||||
{
|
||||
\$criteria = new Criteria();
|
||||
\$criteria->addAscendingOrderByColumn({$this->builder->getColumnConstant($versionForeignColumn)});
|
||||
|
||||
return \$this->get{$relCol}(\$criteria, \$con);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addComputeDiff(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Computes the diff between two versions.
|
||||
* <code>
|
||||
* print_r(\$book->computeDiff(1, 2));
|
||||
* => array(
|
||||
* '1' => array('Title' => 'Book title at version 1'),
|
||||
* '2' => array('Title' => 'Book title at version 2')
|
||||
* );
|
||||
* </code>
|
||||
*
|
||||
* @param array \$fromVersion An array representing the original version.
|
||||
* @param array \$toVersion An array representing the destination version.
|
||||
* @param string \$keys Main key used for the result diff (versions|columns).
|
||||
* @param array \$ignoredColumns The columns to exclude from the diff.
|
||||
*
|
||||
* @return array A list of differences
|
||||
*/
|
||||
protected function computeDiff(\$fromVersion, \$toVersion, \$keys = 'columns', \$ignoredColumns = array())
|
||||
{
|
||||
\$fromVersionNumber = \$fromVersion['{$this->getColumnPhpName()}'];
|
||||
\$toVersionNumber = \$toVersion['{$this->getColumnPhpName()}'];
|
||||
\$ignoredColumns = array_merge(array(
|
||||
'{$this->getColumnPhpName()}',";
|
||||
if ($this->behavior->getParameter('log_created_at') == 'true') {
|
||||
$script .= "
|
||||
'VersionCreatedAt',";
|
||||
}
|
||||
if ($this->behavior->getParameter('log_created_by') == 'true') {
|
||||
$script .= "
|
||||
'VersionCreatedBy',";
|
||||
}
|
||||
if ($this->behavior->getParameter('log_comment') == 'true') {
|
||||
$script .= "
|
||||
'VersionComment',";
|
||||
}
|
||||
$script .= "
|
||||
), \$ignoredColumns);
|
||||
\$diff = array();
|
||||
foreach (\$fromVersion as \$key => \$value) {
|
||||
if (in_array(\$key, \$ignoredColumns)) {
|
||||
continue;
|
||||
}
|
||||
if (\$toVersion[\$key] != \$value) {
|
||||
switch (\$keys) {
|
||||
case 'versions':
|
||||
\$diff[\$fromVersionNumber][\$key] = \$value;
|
||||
\$diff[\$toVersionNumber][\$key] = \$toVersion[\$key];
|
||||
break;
|
||||
default:
|
||||
\$diff[\$key] = array(
|
||||
\$fromVersionNumber => \$value,
|
||||
\$toVersionNumber => \$toVersion[\$key],
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return \$diff;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addCompareVersion(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Compares the current object with another of its version.
|
||||
* <code>
|
||||
* print_r(\$book->compareVersion(1));
|
||||
* => array(
|
||||
* '1' => array('Title' => 'Book title at version 1'),
|
||||
* '2' => array('Title' => 'Book title at version 2')
|
||||
* );
|
||||
* </code>
|
||||
*
|
||||
* @param integer \$versionNumber
|
||||
* @param string \$keys Main key used for the result diff (versions|columns)
|
||||
* @param ConnectionInterface \$con the connection to use
|
||||
* @param array \$ignoredColumns The columns to exclude from the diff.
|
||||
*
|
||||
* @return array A list of differences
|
||||
*/
|
||||
public function compareVersion(\$versionNumber, \$keys = 'columns', \$con = null, \$ignoredColumns = array())
|
||||
{
|
||||
\$fromVersion = \$this->toArray();
|
||||
\$toVersion = \$this->getOneVersion(\$versionNumber, \$con)->toArray();
|
||||
|
||||
return \$this->computeDiff(\$fromVersion, \$toVersion, \$keys, \$ignoredColumns);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addCompareVersions(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Compares two versions of the current object.
|
||||
* <code>
|
||||
* print_r(\$book->compareVersions(1, 2));
|
||||
* => array(
|
||||
* '1' => array('Title' => 'Book title at version 1'),
|
||||
* '2' => array('Title' => 'Book title at version 2')
|
||||
* );
|
||||
* </code>
|
||||
*
|
||||
* @param integer \$fromVersionNumber
|
||||
* @param integer \$toVersionNumber
|
||||
* @param string \$keys Main key used for the result diff (versions|columns)
|
||||
* @param ConnectionInterface \$con the connection to use
|
||||
* @param array \$ignoredColumns The columns to exclude from the diff.
|
||||
*
|
||||
* @return array A list of differences
|
||||
*/
|
||||
public function compareVersions(\$fromVersionNumber, \$toVersionNumber, \$keys = 'columns', \$con = null, \$ignoredColumns = array())
|
||||
{
|
||||
\$fromVersion = \$this->getOneVersion(\$fromVersionNumber, \$con)->toArray();
|
||||
\$toVersion = \$this->getOneVersion(\$toVersionNumber, \$con)->toArray();
|
||||
|
||||
return \$this->computeDiff(\$fromVersion, \$toVersion, \$keys, \$ignoredColumns);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addGetLastVersions(&$script)
|
||||
{
|
||||
$plural = true;
|
||||
$versionTable = $this->behavior->getVersionTable();
|
||||
$versionARClassName = $this->builder->getNewStubObjectBuilder($versionTable)->getClassName();
|
||||
$versionTableMapClassName = $this->builder->getClassNameFromBuilder($this->builder->getNewTableMapBuilder($versionTable));
|
||||
$fks = $versionTable->getForeignKeysReferencingTable($this->table->getName());
|
||||
$relCol = $this->builder->getRefFKPhpNameAffix($fks[0], $plural);
|
||||
$versionGetter = 'get'.$relCol;
|
||||
|
||||
$script .= <<<EOF
|
||||
/**
|
||||
* retrieve the last \$number versions.
|
||||
*
|
||||
* @param Integer \$number the number of record to return.
|
||||
* @return PropelCollection|array {$versionARClassName}[] List of {$versionARClassName} objects
|
||||
*/
|
||||
public function getLastVersions(\$number = 10, \$criteria = null, \$con = null)
|
||||
{
|
||||
\$criteria = {$this->getVersionQueryClassName()}::create(null, \$criteria);
|
||||
\$criteria->addDescendingOrderByColumn({$versionTableMapClassName}::VERSION);
|
||||
\$criteria->limit(\$number);
|
||||
|
||||
return \$this->{$versionGetter}(\$criteria, \$con);
|
||||
}
|
||||
EOF;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
<?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\Behavior\Versionable;
|
||||
|
||||
/**
|
||||
* Behavior to add versionable columns and abilities
|
||||
*
|
||||
* @author François Zaninotto
|
||||
*/
|
||||
class VersionableBehaviorQueryBuilderModifier
|
||||
{
|
||||
protected $behavior;
|
||||
|
||||
protected $table;
|
||||
|
||||
protected $builder;
|
||||
|
||||
protected $objectClassName;
|
||||
|
||||
public function __construct($behavior)
|
||||
{
|
||||
$this->behavior = $behavior;
|
||||
$this->table = $behavior->getTable();
|
||||
}
|
||||
|
||||
public function queryAttributes()
|
||||
{
|
||||
return "
|
||||
/**
|
||||
* Whether the versioning is enabled
|
||||
*/
|
||||
static \$isVersioningEnabled = true;
|
||||
";
|
||||
}
|
||||
|
||||
protected function getParameter($key)
|
||||
{
|
||||
return $this->behavior->getParameter($key);
|
||||
}
|
||||
|
||||
protected function getColumnAttribute($name = 'version_column')
|
||||
{
|
||||
return strtolower($this->behavior->getColumnForParameter($name)->getName());
|
||||
}
|
||||
|
||||
protected function getColumnPhpName($name = 'version_column')
|
||||
{
|
||||
return $this->behavior->getColumnForParameter($name)->getPhpName();
|
||||
}
|
||||
|
||||
protected function getVersionQueryClassName()
|
||||
{
|
||||
return $this->builder->getClassNameFromBuilder($this->builder->getNewStubQueryBuilder($this->behavior->getVersionTable()));
|
||||
}
|
||||
|
||||
protected function setBuilder($builder)
|
||||
{
|
||||
$this->builder = $builder;
|
||||
$this->objectClassName = $builder->getObjectClassName();
|
||||
$this->queryClassName = $builder->getQueryClassName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the getter of the column of the behavior
|
||||
*
|
||||
* @return string The related getter, e.g. 'getVersion'
|
||||
*/
|
||||
protected function getColumnGetter($name = 'version_column')
|
||||
{
|
||||
return 'get' . $this->getColumnPhpName($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the setter of the column of the behavior
|
||||
*
|
||||
* @return string The related setter, e.g. 'setVersion'
|
||||
*/
|
||||
protected function getColumnSetter($name = 'version_column')
|
||||
{
|
||||
return 'set' . $this->getColumnPhpName($name);
|
||||
}
|
||||
|
||||
public function queryMethods($builder)
|
||||
{
|
||||
$this->setBuilder($builder);
|
||||
$script = '';
|
||||
if ('version' !== $this->getParameter('version_column')) {
|
||||
$this->addFilterByVersion($script);
|
||||
$this->addOrderByVersion($script);
|
||||
}
|
||||
|
||||
$script .= $this->addIsVersioningEnabled();
|
||||
$script .= $this->addEnableVersioning();
|
||||
$script .= $this->addDisableVersioning();
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
protected function addFilterByVersion(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Wrap the filter on the version column
|
||||
*
|
||||
* @param integer \$version
|
||||
* @param string \$comparison Operator to use for the column comparison, defaults to Criteria::EQUAL
|
||||
* @return " . $this->builder->getQueryClassName() . " The current query, for fluid interface
|
||||
*/
|
||||
public function filterByVersion(\$version = null, \$comparison = null)
|
||||
{
|
||||
return \$this->filterBy{$this->getColumnPhpName()}(\$version, \$comparison);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addOrderByVersion(&$script)
|
||||
{
|
||||
$script .= "
|
||||
/**
|
||||
* Wrap the order on the version column
|
||||
*
|
||||
* @param string \$order The sorting order. Criteria::ASC by default, also accepts Criteria::DESC
|
||||
* @return " . $this->builder->getQueryClassName() . " The current query, for fluid interface
|
||||
*/
|
||||
public function orderByVersion(\$order = Criteria::ASC)
|
||||
{
|
||||
return \$this->orderBy('{$this->getColumnPhpName()}', \$order);
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addIsVersioningEnabled()
|
||||
{
|
||||
return "
|
||||
/**
|
||||
* Checks whether versioning is enabled
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
static public function isVersioningEnabled()
|
||||
{
|
||||
return self::\$isVersioningEnabled;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addEnableVersioning()
|
||||
{
|
||||
return "
|
||||
/**
|
||||
* Enables versioning
|
||||
*/
|
||||
static public function enableVersioning()
|
||||
{
|
||||
self::\$isVersioningEnabled = true;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
protected function addDisableVersioning()
|
||||
{
|
||||
return "
|
||||
/**
|
||||
* Disables versioning
|
||||
*/
|
||||
static public function disableVersioning()
|
||||
{
|
||||
self::\$isVersioningEnabled = false;
|
||||
}
|
||||
";
|
||||
}
|
||||
}
|
||||
485
core/vendor/propel/propel/src/Propel/Generator/Builder/DataModelBuilder.php
vendored
Normal file
485
core/vendor/propel/propel/src/Propel/Generator/Builder/DataModelBuilder.php
vendored
Normal file
@@ -0,0 +1,485 @@
|
||||
<?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;
|
||||
|
||||
use Propel\Common\Pluralizer\PluralizerInterface;
|
||||
use Propel\Generator\Builder\Om\ObjectBuilder;
|
||||
use Propel\Generator\Builder\Om\QueryBuilder;
|
||||
use Propel\Generator\Builder\Om\TableMapBuilder;
|
||||
use Propel\Generator\Builder\Sql\DataSQLBuilder;
|
||||
use Propel\Generator\Config\GeneratorConfigInterface;
|
||||
use Propel\Generator\Model\Database;
|
||||
use Propel\Generator\Model\Table;
|
||||
use Propel\Generator\Platform\PlatformInterface;
|
||||
|
||||
/**
|
||||
* This is the base class for any builder class that is using the data model.
|
||||
*
|
||||
* This could be extended by classes that build SQL DDL, PHP classes, configuration
|
||||
* files, input forms, etc.
|
||||
*
|
||||
* The GeneratorConfig needs to be set on this class in order for the builders
|
||||
* to be able to access the propel generator build properties. You should be
|
||||
* safe if you always use the GeneratorConfig to get a configured builder class
|
||||
* anyway.
|
||||
*
|
||||
* @author Hans Lellelid <hans@xmpl.org>
|
||||
*/
|
||||
abstract class DataModelBuilder
|
||||
{
|
||||
|
||||
/**
|
||||
* The current table.
|
||||
* @var Table
|
||||
*/
|
||||
private $table;
|
||||
|
||||
/**
|
||||
* The generator config object holding build properties, etc.
|
||||
*
|
||||
* @var GeneratorConfigInterface
|
||||
*/
|
||||
private $generatorConfig;
|
||||
|
||||
/**
|
||||
* An array of warning messages that can be retrieved for display.
|
||||
* @var array string[]
|
||||
*/
|
||||
private $warnings = array();
|
||||
|
||||
/**
|
||||
* Object builder class for current table.
|
||||
* @var DataModelBuilder
|
||||
*/
|
||||
private $objectBuilder;
|
||||
|
||||
/**
|
||||
* Stub Object builder class for current table.
|
||||
* @var DataModelBuilder
|
||||
*/
|
||||
private $stubObjectBuilder;
|
||||
|
||||
/**
|
||||
* Query builder class for current table.
|
||||
* @var DataModelBuilder
|
||||
*/
|
||||
private $queryBuilder;
|
||||
|
||||
/**
|
||||
* Stub Query builder class for current table.
|
||||
* @var DataModelBuilder
|
||||
*/
|
||||
private $stubQueryBuilder;
|
||||
|
||||
/**
|
||||
* TableMap builder class for current table.
|
||||
* @var DataModelBuilder
|
||||
*/
|
||||
protected $tablemapBuilder;
|
||||
|
||||
/**
|
||||
* Stub Interface builder class for current table.
|
||||
* @var DataModelBuilder
|
||||
*/
|
||||
private $interfaceBuilder;
|
||||
|
||||
/**
|
||||
* Stub child object for current table.
|
||||
* @var DataModelBuilder
|
||||
*/
|
||||
private $multiExtendObjectBuilder;
|
||||
|
||||
/**
|
||||
* The Data-SQL builder for current table.
|
||||
* @var DataSQLBuilder
|
||||
*/
|
||||
private $dataSqlBuilder;
|
||||
|
||||
/**
|
||||
* The Pluralizer class to use.
|
||||
* @var PluralizerInterface
|
||||
*/
|
||||
private $pluralizer;
|
||||
|
||||
/**
|
||||
* The platform class
|
||||
* @var PlatformInterface
|
||||
*/
|
||||
protected $platform;
|
||||
|
||||
/**
|
||||
* Creates new instance of DataModelBuilder subclass.
|
||||
* @param Table $table The Table which we are using to build [OM, DDL, etc.].
|
||||
*/
|
||||
public function __construct(Table $table)
|
||||
{
|
||||
$this->table = $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns new or existing Pluralizer class.
|
||||
* @return PluralizerInterface
|
||||
*/
|
||||
public function getPluralizer()
|
||||
{
|
||||
if (!isset($this->pluralizer)) {
|
||||
$this->pluralizer = $this->getGeneratorConfig()->getConfiguredPluralizer();
|
||||
}
|
||||
|
||||
return $this->pluralizer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns new or existing Object builder class for this table.
|
||||
* @return ObjectBuilder
|
||||
*/
|
||||
public function getObjectBuilder()
|
||||
{
|
||||
if (!isset($this->objectBuilder)) {
|
||||
$this->objectBuilder = $this->getGeneratorConfig()->getConfiguredBuilder($this->getTable(), 'object');
|
||||
}
|
||||
|
||||
return $this->objectBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns new or existing stub Object builder class for this table.
|
||||
* @return ObjectBuilder
|
||||
*/
|
||||
public function getStubObjectBuilder()
|
||||
{
|
||||
if (!isset($this->stubObjectBuilder)) {
|
||||
$this->stubObjectBuilder = $this->getGeneratorConfig()->getConfiguredBuilder($this->getTable(), 'objectstub');
|
||||
}
|
||||
|
||||
return $this->stubObjectBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns new or existing Query builder class for this table.
|
||||
* @return ObjectBuilder
|
||||
*/
|
||||
public function getQueryBuilder()
|
||||
{
|
||||
if (!isset($this->queryBuilder)) {
|
||||
$this->queryBuilder = $this->getGeneratorConfig()->getConfiguredBuilder($this->getTable(), 'query');
|
||||
}
|
||||
|
||||
return $this->queryBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns new or existing stub Query builder class for this table.
|
||||
* @return ObjectBuilder
|
||||
*/
|
||||
public function getStubQueryBuilder()
|
||||
{
|
||||
if (!isset($this->stubQueryBuilder)) {
|
||||
$this->stubQueryBuilder = $this->getGeneratorConfig()->getConfiguredBuilder($this->getTable(), 'querystub');
|
||||
}
|
||||
|
||||
return $this->stubQueryBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns new or existing Object builder class for this table.
|
||||
* @return ObjectBuilder
|
||||
*/
|
||||
public function getTableMapBuilder()
|
||||
{
|
||||
if (!isset($this->tablemapBuilder)) {
|
||||
$this->tablemapBuilder = $this->getGeneratorConfig()->getConfiguredBuilder($this->getTable(), 'tablemap');
|
||||
}
|
||||
|
||||
return $this->tablemapBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns new or existing stub Interface builder class for this table.
|
||||
* @return ObjectBuilder
|
||||
*/
|
||||
public function getInterfaceBuilder()
|
||||
{
|
||||
if (!isset($this->interfaceBuilder)) {
|
||||
$this->interfaceBuilder = $this->getGeneratorConfig()->getConfiguredBuilder($this->getTable(), 'interface');
|
||||
}
|
||||
|
||||
return $this->interfaceBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns new or existing stub child object builder class for this table.
|
||||
* @return ObjectBuilder
|
||||
*/
|
||||
public function getMultiExtendObjectBuilder()
|
||||
{
|
||||
if (!isset($this->multiExtendObjectBuilder)) {
|
||||
$this->multiExtendObjectBuilder = $this->getGeneratorConfig()->getConfiguredBuilder($this->getTable(), 'objectmultiextend');
|
||||
}
|
||||
|
||||
return $this->multiExtendObjectBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns new or existing data sql builder class for this table.
|
||||
* @return DataSQLBuilder
|
||||
*/
|
||||
public function getDataSQLBuilder()
|
||||
{
|
||||
if (!isset($this->dataSqlBuilder)) {
|
||||
$this->dataSqlBuilder = $this->getGeneratorConfig()->getConfiguredBuilder($this->getTable(), 'datasql');
|
||||
}
|
||||
|
||||
return $this->dataSqlBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a new data model builder class for specified table and classname.
|
||||
*
|
||||
* @param Table $table
|
||||
* @param string $classname The class of builder
|
||||
* @return DataModelBuilder
|
||||
*/
|
||||
public function getNewBuilder(Table $table, $classname)
|
||||
{
|
||||
$builder = new $classname($table);
|
||||
$builder->setGeneratorConfig($this);
|
||||
|
||||
return $builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to return a NEW Object class builder instance.
|
||||
*
|
||||
* This is used very frequently from the tableMap and object builders to get
|
||||
* an object builder for a RELATED table.
|
||||
*
|
||||
* @param Table $table
|
||||
* @return ObjectBuilder
|
||||
*/
|
||||
public function getNewObjectBuilder(Table $table)
|
||||
{
|
||||
return $this->getGeneratorConfig()->getConfiguredBuilder($table, 'object');
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to return a NEW Object stub class builder instance.
|
||||
*
|
||||
* This is used from the query builders to get
|
||||
* an object builder for a RELATED table.
|
||||
*
|
||||
* @param Table $table
|
||||
* @return ObjectBuilder
|
||||
*/
|
||||
public function getNewStubObjectBuilder(Table $table)
|
||||
{
|
||||
return $this->getGeneratorConfig()->getConfiguredBuilder($table, 'objectstub');
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to return a NEW query class builder instance.
|
||||
*
|
||||
* This is used from the query builders to get
|
||||
* a query builder for a RELATED table.
|
||||
*
|
||||
* @param Table $table
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
public function getNewQueryBuilder(Table $table)
|
||||
{
|
||||
return $this->getGeneratorConfig()->getConfiguredBuilder($table, 'query');
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to return a NEW query stub class builder instance.
|
||||
*
|
||||
* This is used from the query builders to get
|
||||
* a query builder for a RELATED table.
|
||||
*
|
||||
* @param Table $table
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
public function getNewStubQueryBuilder(Table $table)
|
||||
{
|
||||
return $this->getGeneratorConfig()->getConfiguredBuilder($table, 'querystub');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns new Query Inheritance builder class for this table.
|
||||
* @return ObjectBuilder
|
||||
*/
|
||||
public function getNewQueryInheritanceBuilder($child)
|
||||
{
|
||||
$queryInheritanceBuilder = $this->getGeneratorConfig()->getConfiguredBuilder($this->getTable(), 'queryinheritance');
|
||||
$queryInheritanceBuilder->setChild($child);
|
||||
|
||||
return $queryInheritanceBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns new stub Query Inheritance builder class for this table.
|
||||
* @return ObjectBuilder
|
||||
*/
|
||||
public function getNewStubQueryInheritanceBuilder($child)
|
||||
{
|
||||
$stubQueryInheritanceBuilder = $this->getGeneratorConfig()->getConfiguredBuilder($this->getTable(), 'queryinheritancestub');
|
||||
$stubQueryInheritanceBuilder->setChild($child);
|
||||
|
||||
return $stubQueryInheritanceBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns new stub Query Inheritance builder class for this table.
|
||||
* @return TableMapBuilder
|
||||
*/
|
||||
public function getNewTableMapBuilder(Table $table)
|
||||
{
|
||||
return $this->getGeneratorConfig()->getConfiguredBuilder($table, 'tablemap');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the GeneratorConfig object.
|
||||
*
|
||||
* @return GeneratorConfigInterface
|
||||
*/
|
||||
public function getGeneratorConfig()
|
||||
{
|
||||
return $this->generatorConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific [name transformed] build property.
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
public function getBuildProperty($name)
|
||||
{
|
||||
if ($this->getGeneratorConfig()) {
|
||||
return $this->getGeneratorConfig()->getBuildProperty($name);
|
||||
}
|
||||
|
||||
return null; // just to be explicit
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the GeneratorConfig object.
|
||||
*
|
||||
* @param GeneratorConfigInterface $v
|
||||
*/
|
||||
public function setGeneratorConfig(GeneratorConfigInterface $v)
|
||||
{
|
||||
$this->generatorConfig = $v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the table for this builder.
|
||||
* @param Table $table
|
||||
*/
|
||||
public function setTable(Table $table)
|
||||
{
|
||||
$this->table = $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current Table object.
|
||||
* @return Table
|
||||
*/
|
||||
public function getTable()
|
||||
{
|
||||
return $this->table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to returns the Platform class for this table (database).
|
||||
* @return PlatformInterface
|
||||
*/
|
||||
public function getPlatform()
|
||||
{
|
||||
if (null === $this->platform) {
|
||||
// try to load the platform from the table
|
||||
$table = $this->getTable();
|
||||
if ($table && $database = $table->getDatabase()) {
|
||||
$this->setPlatform($database->getPlatform());
|
||||
}
|
||||
}
|
||||
|
||||
return $this->platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Platform setter
|
||||
*
|
||||
* @param PlatformInterface $platform
|
||||
*/
|
||||
public function setPlatform(PlatformInterface $platform)
|
||||
{
|
||||
$this->platform = $platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to returns the database for current table.
|
||||
* @return Database
|
||||
*/
|
||||
public function getDatabase()
|
||||
{
|
||||
if ($this->getTable()) {
|
||||
return $this->getTable()->getDatabase();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes a message onto the stack of warnings.
|
||||
* @param string $msg The warning message.
|
||||
*/
|
||||
protected function warn($msg)
|
||||
{
|
||||
$this->warnings[] = $msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets array of warning messages.
|
||||
* @return string[]
|
||||
*/
|
||||
public function getWarnings()
|
||||
{
|
||||
return $this->warnings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps call to Platform->quoteIdentifier() with a check to see whether quoting is enabled.
|
||||
*
|
||||
* All subclasses should call this quoteIdentifier() method rather than calling the Platform
|
||||
* method directly. This method is used by both DataSQLBuilder and DDLBuilder, and potentially
|
||||
* in the OM builders also, which is why it is defined in this class.
|
||||
*
|
||||
* @param string $text The text to quote.
|
||||
* @return string Quoted text.
|
||||
*/
|
||||
public function quoteIdentifier($text)
|
||||
{
|
||||
if (!$this->getBuildProperty('disableIdentifierQuoting')) {
|
||||
return $this->getPlatform()->quoteIdentifier($text);
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the current class being built, with a possible prefix.
|
||||
* @return string
|
||||
* @see OMBuilder#getClassName()
|
||||
*/
|
||||
public function prefixClassName($identifier)
|
||||
{
|
||||
return $this->getBuildProperty('classPrefix') . $identifier;
|
||||
}
|
||||
}
|
||||
834
core/vendor/propel/propel/src/Propel/Generator/Builder/Om/AbstractOMBuilder.php
vendored
Normal file
834
core/vendor/propel/propel/src/Propel/Generator/Builder/Om/AbstractOMBuilder.php
vendored
Normal file
@@ -0,0 +1,834 @@
|
||||
<?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\Builder\DataModelBuilder;
|
||||
use Propel\Generator\Builder\Util\PropelTemplate;
|
||||
use Propel\Generator\Exception\InvalidArgumentException;
|
||||
use Propel\Generator\Exception\LogicException;
|
||||
use Propel\Generator\Exception\RuntimeException;
|
||||
use Propel\Generator\Model\Column;
|
||||
use Propel\Generator\Model\ForeignKey;
|
||||
use Propel\Generator\Model\Table;
|
||||
|
||||
/**
|
||||
* Baseclass for OM-building classes.
|
||||
*
|
||||
* OM-building classes are those that build a PHP (or other) class to service
|
||||
* a single table. This includes Entity classes, Map classes,
|
||||
* Node classes, Nested Set classes, etc.
|
||||
*
|
||||
* @author Hans Lellelid <hans@xmpl.org>
|
||||
*/
|
||||
abstract class AbstractOMBuilder extends DataModelBuilder
|
||||
{
|
||||
/**
|
||||
* Declared fully qualified classnames, to build the 'namespace' statements
|
||||
* according to this table's namespace.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $declaredClasses = array();
|
||||
|
||||
/**
|
||||
* Mapping between fully qualified classnames and their short classname or alias
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $declaredShortClassesOrAlias = array();
|
||||
|
||||
/**
|
||||
* List of classes that can be use without alias when model don't have namespace
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $whiteListOfDeclaredClasses = array('PDO', 'Exception', 'DateTime');
|
||||
|
||||
/**
|
||||
* Builds the PHP source for current class and returns it as a string.
|
||||
*
|
||||
* This is the main entry point and defines a basic structure that classes should follow.
|
||||
* In most cases this method will not need to be overridden by subclasses. This method
|
||||
* does assume that the output language is PHP code, so it will need to be overridden if
|
||||
* this is not the case.
|
||||
*
|
||||
* @return string The resulting PHP sourcecode.
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
$this->validateModel();
|
||||
$this->declareClass($this->getFullyQualifiedClassName());
|
||||
|
||||
$script = '';
|
||||
$this->addClassOpen($script);
|
||||
$this->addClassBody($script);
|
||||
$this->addClassClose($script);
|
||||
|
||||
$ignoredNamespace = $this->getNamespace();
|
||||
|
||||
if ($useStatements = $this->getUseStatements($ignoredNamespace ?: 'namespace')) {
|
||||
$script = $useStatements . $script;
|
||||
}
|
||||
|
||||
if ($namespaceStatement = $this->getNamespaceStatement()) {
|
||||
$script = $namespaceStatement . $script;
|
||||
}
|
||||
|
||||
$script = "<?php
|
||||
|
||||
" . $script;
|
||||
|
||||
return $this->clean($script);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the current table to make sure that it won't
|
||||
* result in generated code that will not parse.
|
||||
*
|
||||
* This method may emit warnings for code which may cause problems
|
||||
* and will throw exceptions for errors that will definitely cause
|
||||
* problems.
|
||||
*/
|
||||
protected function validateModel()
|
||||
{
|
||||
// Validation is currently only implemented in the subclasses.
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a $obj = new Book(); code snippet. Can be used by frameworks, for instance, to
|
||||
* extend this behavior, e.g. initialize the object after creating the instance or so.
|
||||
*
|
||||
* @return string Some code
|
||||
*/
|
||||
public function buildObjectInstanceCreationCode($objName, $clsName)
|
||||
{
|
||||
return "$objName = new $clsName();";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the qualified (prefixed) classname that is being built by the current class.
|
||||
* This method must be implemented by child classes.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function getUnprefixedClassName();
|
||||
|
||||
/**
|
||||
* Returns the unqualified classname (e.g. Book)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUnqualifiedClassName()
|
||||
{
|
||||
return $this->getUnprefixedClassName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the qualified classname (e.g. Model\Book)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedClassName()
|
||||
{
|
||||
if ($namespace = $this->getNamespace()) {
|
||||
return $namespace . '\\' . $this->getUnqualifiedClassName();
|
||||
}
|
||||
|
||||
return $this->getUnqualifiedClassName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fully qualified classname (e.g. \Model\Book)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFullyQualifiedClassName()
|
||||
{
|
||||
return '\\' . $this->getQualifiedClassName();
|
||||
}
|
||||
/**
|
||||
* Returns FQCN alias of getFullyQualifiedClassName
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getClassName()
|
||||
{
|
||||
return $this->getFullyQualifiedClassName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the dot-path representation of current class being built.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getClasspath()
|
||||
{
|
||||
if ($this->getPackage()) {
|
||||
return $this->getPackage() . '.' . $this->getUnqualifiedClassName();
|
||||
}
|
||||
|
||||
return $this->getUnqualifiedClassName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the full path to the file for the current class.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getClassFilePath()
|
||||
{
|
||||
return ClassTools::createFilePath($this->getPackagePath(), $this->getUnqualifiedClassName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets package name for this table.
|
||||
* This is overridden by child classes that have different packages.
|
||||
* @return string
|
||||
*/
|
||||
public function getPackage()
|
||||
{
|
||||
$pkg = ($this->getTable()->getPackage() ? $this->getTable()->getPackage() : $this->getDatabase()->getPackage());
|
||||
if (!$pkg) {
|
||||
$pkg = $this->getBuildProperty('targetPackage');
|
||||
}
|
||||
|
||||
return $pkg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns filesystem path for current package.
|
||||
* @return string
|
||||
*/
|
||||
public function getPackagePath()
|
||||
{
|
||||
$pkg = $this->getPackage();
|
||||
|
||||
if (false !== strpos($pkg, '/')) {
|
||||
$pkg = preg_replace('#\.(map|om)$#', '/\1', $pkg);
|
||||
$pkg = preg_replace('#\.(Map|Om)$#', '/\1', $pkg);
|
||||
|
||||
return $pkg;
|
||||
}
|
||||
|
||||
return strtr($pkg, '.', '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user-defined namespace for this table,
|
||||
* or the database namespace otherwise.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getNamespace()
|
||||
{
|
||||
return $this->getTable()->getNamespace();
|
||||
}
|
||||
|
||||
/**
|
||||
* This declare the class use and get the correct name to use (short classname, Alias, or FQCN)
|
||||
*
|
||||
* @param AbstractOMBuilder $builder
|
||||
* @param boolean $fqcn true to return the $fqcn classname
|
||||
* @return string ClassName, Alias or FQCN
|
||||
*/
|
||||
public function getClassNameFromBuilder($builder, $fqcn = false)
|
||||
{
|
||||
if ($fqcn) {
|
||||
return $builder->getFullyQualifiedClassName();
|
||||
}
|
||||
|
||||
$namespace = $builder->getNamespace();
|
||||
$class = $builder->getUnqualifiedClassName();
|
||||
|
||||
if (isset($this->declaredClasses[$namespace])
|
||||
&& isset($this->declaredClasses[$namespace][$class])) {
|
||||
return $this->declaredClasses[$namespace][$class];
|
||||
}
|
||||
|
||||
return $this->declareClassNamespace($class, $namespace, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Declare a class to be use and return it's name or it's alias
|
||||
*
|
||||
* @param string $class the class name
|
||||
* @param string $namespace the namespace
|
||||
* @param string|boolean $alias the alias wanted, if set to True, it automatically adds an alias when needed
|
||||
* @return string the class name or it's alias
|
||||
*/
|
||||
public function declareClassNamespace($class, $namespace = '', $alias = false)
|
||||
{
|
||||
// check if the class is already declared
|
||||
if (isset($this->declaredClasses[$namespace])
|
||||
&& isset($this->declaredClasses[$namespace][$class])) {
|
||||
return $this->declaredClasses[$namespace][$class];
|
||||
}
|
||||
|
||||
$forcedAlias = $this->needAliasForClassName($class, $namespace);
|
||||
|
||||
if (false === $alias || true === $alias || null === $alias) {
|
||||
$aliasWanted = $class;
|
||||
$alias = $alias || $forcedAlias;
|
||||
} else {
|
||||
$aliasWanted = $alias;
|
||||
$forcedAlias = false;
|
||||
}
|
||||
|
||||
if (!$forcedAlias && !isset($this->declaredShortClassesOrAlias[$aliasWanted])) {
|
||||
if (!isset($this->declaredClasses[$namespace])) {
|
||||
$this->declaredClasses[$namespace] = array();
|
||||
}
|
||||
|
||||
$this->declaredClasses[$namespace][$class] = $aliasWanted;
|
||||
$this->declaredShortClassesOrAlias[$aliasWanted] = $namespace . '\\' . $class;
|
||||
|
||||
return $aliasWanted;
|
||||
}
|
||||
|
||||
// we have a duplicate class and asked for an automatic Alias
|
||||
if (false !== $alias) {
|
||||
if ('\\Base' == substr($namespace, -5) || 'Base' == $namespace) {
|
||||
return $this->declareClassNamespace($class, $namespace, 'Base' . $class);
|
||||
}
|
||||
|
||||
return $this->declareClassNamespace($class, $namespace, 'Child' . $class);
|
||||
}
|
||||
|
||||
throw new LogicException(sprintf(
|
||||
'The class %s duplicates the class %s and can\'t be used without alias',
|
||||
$namespace . '\\' . $class,
|
||||
$this->declaredShortClassesOrAlias[$aliasWanted]
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* check if the current $class need an alias or if the class could be used with a shortname without conflict
|
||||
* @param string $class
|
||||
* @param string $namespace
|
||||
*/
|
||||
protected function needAliasForClassName($class, $namespace)
|
||||
{
|
||||
if ($namespace == $this->getNamespace()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (str_replace('\\Base', '', $namespace) == str_replace('\\Base', '', $this->getNamespace())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (empty($namespace) && 'Base' === $this->getNamespace()) {
|
||||
if (str_replace(array('Query'), '', $class) == str_replace(array('Query'), '', $this->getUnqualifiedClassName())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((false !== strpos($class, 'Query'))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// force alias for model without namespace
|
||||
if (false === array_search($class, $this->whiteListOfDeclaredClasses, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ('Base' === $namespace && '' === $this->getNamespace()) {
|
||||
// force alias for model without namespace
|
||||
if (false === array_search($class, $this->whiteListOfDeclaredClasses, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Declare a use statement for a $class with a $namespace and an $aliasPrefix
|
||||
* This return the short ClassName or an alias
|
||||
*
|
||||
* @param string $class the class
|
||||
* @param string $namespace the namespace
|
||||
* @param mixed $aliasPrefix optionally an alias or True to force an automatic alias prefix (Base or Child)
|
||||
* @return string the short ClassName or an alias
|
||||
*/
|
||||
public function declareClassNamespacePrefix($class, $namespace = '', $aliasPrefix = false)
|
||||
{
|
||||
if (false !== $aliasPrefix && true !== $aliasPrefix) {
|
||||
$alias = $aliasPrefix . $class;
|
||||
} else {
|
||||
$alias = $aliasPrefix;
|
||||
}
|
||||
|
||||
return $this->declareClassNamespace($class, $namespace, $alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Declare a Fully qualified classname with an $aliasPrefix
|
||||
* This return the short ClassName to use or an alias
|
||||
*
|
||||
* @param string $fullyQualifiedClassName the fully qualified classname
|
||||
* @param mixed $aliasPrefix optionally an alias or True to force an automatic alias prefix (Base or Child)
|
||||
* @return string the short ClassName or an alias
|
||||
*/
|
||||
public function declareClass($fullyQualifiedClassName, $aliasPrefix = false)
|
||||
{
|
||||
$fullyQualifiedClassName = trim($fullyQualifiedClassName, '\\');
|
||||
if (($pos = strrpos($fullyQualifiedClassName, '\\')) !== false) {
|
||||
return $this->declareClassNamespacePrefix(substr($fullyQualifiedClassName, $pos + 1), substr($fullyQualifiedClassName, 0, $pos), $aliasPrefix);
|
||||
}
|
||||
// root namespace
|
||||
return $this->declareClassNamespacePrefix($fullyQualifiedClassName, '', $aliasPrefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $builder
|
||||
* @param boolean|string $aliasPrefix the prefix for the Alias or True for auto generation of the Alias
|
||||
*/
|
||||
public function declareClassFromBuilder($builder, $aliasPrefix = false)
|
||||
{
|
||||
return $this->declareClassNamespacePrefix($builder->getUnqualifiedClassName(), $builder->getNamespace(), $aliasPrefix);
|
||||
}
|
||||
|
||||
public function declareClasses()
|
||||
{
|
||||
$args = func_get_args();
|
||||
foreach ($args as $class) {
|
||||
$this->declareClass($class);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of declared classes for a given $namespace or all declared classes
|
||||
*
|
||||
* @param string $namespace the namespace or null
|
||||
* @return array list of declared classes
|
||||
*/
|
||||
public function getDeclaredClasses($namespace = null)
|
||||
{
|
||||
if (null !== $namespace && isset($this->declaredClasses[$namespace])) {
|
||||
return $this->declaredClasses[$namespace];
|
||||
}
|
||||
|
||||
return $this->declaredClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* return the string for the class namespace
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getNamespaceStatement()
|
||||
{
|
||||
$namespace = $this->getNamespace();
|
||||
if (!empty($namespace)) {
|
||||
return sprintf("namespace %s;
|
||||
|
||||
", $namespace);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the use statement of the class
|
||||
*
|
||||
* @param string $ignoredNamespace the ignored namespace
|
||||
* @return string
|
||||
*/
|
||||
public function getUseStatements($ignoredNamespace = null)
|
||||
{
|
||||
$script = '';
|
||||
$declaredClasses = $this->declaredClasses;
|
||||
unset($declaredClasses[$ignoredNamespace]);
|
||||
ksort($declaredClasses);
|
||||
foreach ($declaredClasses as $namespace => $classes) {
|
||||
asort($classes);
|
||||
foreach ($classes as $class => $alias) {
|
||||
// Don't use our own class
|
||||
if ($class == $this->getUnqualifiedClassName() && $namespace == $this->getNamespace()) {
|
||||
continue;
|
||||
}
|
||||
if ($class == $alias) {
|
||||
$script .= sprintf("use %s\\%s;
|
||||
", $namespace, $class);
|
||||
} else {
|
||||
$script .= sprintf("use %s\\%s as %s;
|
||||
", $namespace, $class, $alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut method to return the [stub] query classname for current table.
|
||||
* This is the classname that is used whenever object or tablemap classes want
|
||||
* to invoke methods of the query classes.
|
||||
* @param boolean $fqcn
|
||||
* @return string (e.g. 'Myquery')
|
||||
*/
|
||||
public function getQueryClassName($fqcn = false)
|
||||
{
|
||||
return $this->getClassNameFromBuilder($this->getStubQueryBuilder(), $fqcn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object classname for current table.
|
||||
* This is the classname that is used whenever object or tablemap classes want
|
||||
* to invoke methods of the object classes.
|
||||
* @param boolean $fqcn
|
||||
* @return string (e.g. 'My')
|
||||
*/
|
||||
public function getObjectClassName($fqcn = false)
|
||||
{
|
||||
return $this->getClassNameFromBuilder($this->getStubObjectBuilder(), $fqcn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tableMap classname for current table.
|
||||
* This is the classname that is used whenever object or tablemap classes want
|
||||
* to invoke methods of the object classes.
|
||||
* @param boolean $fqcn
|
||||
* @return string (e.g. 'My')
|
||||
*/
|
||||
public function getTableMapClassName($fqcn = false)
|
||||
{
|
||||
return $this->getClassNameFromBuilder($this->getTableMapBuilder(), $fqcn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column constant name (e.g. TableMapName::COLUMN_NAME).
|
||||
*
|
||||
* @param Column $col The column we need a name for.
|
||||
* @param string $classname The TableMap classname to use.
|
||||
*
|
||||
* @return string If $classname is provided, then will return $classname::COLUMN_NAME; if not, then the TableMapName is looked up for current table to yield $currTableTableMap::COLUMN_NAME.
|
||||
*/
|
||||
public function getColumnConstant($col, $classname = null)
|
||||
{
|
||||
if (null === $col) {
|
||||
throw new InvalidArgumentException('No columns were specified.');
|
||||
}
|
||||
|
||||
if (null === $classname) {
|
||||
return $this->getBuildProperty('classPrefix') . $col->getConstantName();
|
||||
}
|
||||
|
||||
// was it overridden in schema.xml ?
|
||||
if ($col->getTableMapName()) {
|
||||
$const = strtoupper($col->getTableMapName());
|
||||
} else {
|
||||
$const = strtoupper($col->getName());
|
||||
}
|
||||
|
||||
return $classname.'::'.$const;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to get the default Join Type for a relation.
|
||||
* If the key is required, an INNER JOIN will be returned, else a LEFT JOIN will be suggested,
|
||||
* unless the schema is provided with the DefaultJoin attribute, which overrules the default Join Type
|
||||
*
|
||||
* @param ForeignKey $fk
|
||||
* @return string
|
||||
*/
|
||||
protected function getJoinType(ForeignKey $fk)
|
||||
{
|
||||
if ($defaultJoin = $fk->getDefaultJoin()) {
|
||||
return "'" . $defaultJoin . "'";
|
||||
}
|
||||
|
||||
if ($fk->isLocalColumnsRequired()) {
|
||||
return 'Criteria::INNER_JOIN';
|
||||
}
|
||||
|
||||
return 'Criteria::LEFT_JOIN';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the PHP method name affix to be used for fkeys for the current table (not referrers to this table).
|
||||
*
|
||||
* The difference between this method and the getRefFKPhpNameAffix() method is that in this method the
|
||||
* classname in the affix is the foreign table classname.
|
||||
*
|
||||
* @param ForeignKey $fk The local FK that we need a name for.
|
||||
* @param boolean $plural Whether the php name should be plural (e.g. initRelatedObjs() vs. addRelatedObj()
|
||||
* @return string
|
||||
*/
|
||||
public function getFKPhpNameAffix(ForeignKey $fk, $plural = false)
|
||||
{
|
||||
if ($fk->getPhpName()) {
|
||||
if ($plural) {
|
||||
return $this->getPluralizer()->getPluralForm($fk->getPhpName());
|
||||
}
|
||||
|
||||
return $fk->getPhpName();
|
||||
}
|
||||
|
||||
$className = $fk->getForeignTable()->getPhpName();
|
||||
if ($plural) {
|
||||
$className = $this->getPluralizer()->getPluralForm($className);
|
||||
}
|
||||
|
||||
return $className . $this->getRelatedBySuffix($fk);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the "RelatedBy*" suffix (if needed) that is attached to method and variable names.
|
||||
*
|
||||
* The related by suffix is based on the local columns of the foreign key. If there is more than
|
||||
* one column in a table that points to the same foreign table, then a 'RelatedByLocalColName' suffix
|
||||
* will be appended.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function getRelatedBySuffix(ForeignKey $fk)
|
||||
{
|
||||
$relCol = '';
|
||||
foreach ($fk->getLocalForeignMapping() as $localColumnName => $foreignColumnName) {
|
||||
$localTable = $fk->getTable();
|
||||
$localColumn = $localTable->getColumn($localColumnName);
|
||||
if (!$localColumn) {
|
||||
throw new RuntimeException(sprintf('Could not fetch column: %s in table %s.', $localColumnName, $localTable->getName()));
|
||||
}
|
||||
|
||||
if (count($localTable->getForeignKeysReferencingTable($fk->getForeignTableName())) > 1
|
||||
|| count($fk->getForeignTable()->getForeignKeysReferencingTable($fk->getTableName())) > 0
|
||||
|| $fk->getForeignTableName() == $fk->getTableName()) {
|
||||
// self referential foreign key, or several foreign keys to the same table, or cross-reference fkey
|
||||
$relCol .= $localColumn->getPhpName();
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($relCol)) {
|
||||
$relCol = 'RelatedBy' . $relCol;
|
||||
}
|
||||
|
||||
return $relCol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the PHP method name affix to be used for referencing foreign key methods and variable names (e.g. set????(), $coll???).
|
||||
*
|
||||
* The difference between this method and the getFKPhpNameAffix() method is that in this method the
|
||||
* classname in the affix is the classname of the local fkey table.
|
||||
*
|
||||
* @param ForeignKey $fk The referrer FK that we need a name for.
|
||||
* @param boolean $plural Whether the php name should be plural (e.g. initRelatedObjs() vs. addRelatedObj()
|
||||
* @return string
|
||||
*/
|
||||
public function getRefFKPhpNameAffix(ForeignKey $fk, $plural = false)
|
||||
{
|
||||
$pluralizer = $this->getPluralizer();
|
||||
if ($fk->getRefPhpName()) {
|
||||
return $plural ? $pluralizer->getPluralForm($fk->getRefPhpName()) : $fk->getRefPhpName();
|
||||
}
|
||||
|
||||
$className = $fk->getTable()->getPhpName();
|
||||
if ($plural) {
|
||||
$className = $pluralizer->getPluralForm($className);
|
||||
}
|
||||
|
||||
return $className . $this->getRefRelatedBySuffix($fk);
|
||||
}
|
||||
|
||||
protected static function getRefRelatedBySuffix(ForeignKey $fk)
|
||||
{
|
||||
$relCol = '';
|
||||
foreach ($fk->getLocalForeignMapping() as $localColumnName => $foreignColumnName) {
|
||||
$localTable = $fk->getTable();
|
||||
$localColumn = $localTable->getColumn($localColumnName);
|
||||
if (!$localColumn) {
|
||||
throw new RuntimeException(sprintf('Could not fetch column: %s in table %s.', $localColumnName, $localTable->getName()));
|
||||
}
|
||||
$foreignKeysToForeignTable = $localTable->getForeignKeysReferencingTable($fk->getForeignTableName());
|
||||
if ($fk->getForeignTableName() == $fk->getTableName()) {
|
||||
// self referential foreign key
|
||||
$relCol .= $fk->getForeignTable()->getColumn($foreignColumnName)->getPhpName();
|
||||
if (count($foreignKeysToForeignTable) > 1) {
|
||||
// several self-referential foreign keys
|
||||
$relCol .= array_search($fk, $foreignKeysToForeignTable);
|
||||
}
|
||||
} elseif (count($foreignKeysToForeignTable) > 1 || count($fk->getForeignTable()->getForeignKeysReferencingTable($fk->getTableName())) > 0) {
|
||||
// several foreign keys to the same table, or symmetrical foreign key in foreign table
|
||||
$relCol .= $localColumn->getPhpName();
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($relCol)) {
|
||||
$relCol = 'RelatedBy' . $relCol;
|
||||
}
|
||||
|
||||
return $relCol;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 $modifier The name of the modifier object providing the method in the behavior
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasBehaviorModifier($hookName, $modifier)
|
||||
{
|
||||
$modifierGetter = 'get' . $modifier;
|
||||
foreach ($this->getTable()->getBehaviors() as $behavior) {
|
||||
if (method_exists($behavior->$modifierGetter(), $hookName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 $modifier The name of the modifier object providing the method in the behavior
|
||||
* @param string &$script The script will be modified in this method.
|
||||
*/
|
||||
public function applyBehaviorModifierBase($hookName, $modifier, &$script, $tab = " ")
|
||||
{
|
||||
$modifierGetter = 'get' . $modifier;
|
||||
foreach ($this->getTable()->getBehaviors() as $behavior) {
|
||||
$modifier = $behavior->$modifierGetter();
|
||||
if (method_exists($modifier, $hookName)) {
|
||||
if (strpos($hookName, 'Filter') !== false) {
|
||||
// filter hook: the script string will be modified by the behavior
|
||||
$modifier->$hookName($script, $this);
|
||||
} else {
|
||||
// regular hook: the behavior returns a string to append to the script string
|
||||
if (!$addedScript = $modifier->$hookName($this)) {
|
||||
continue;
|
||||
}
|
||||
$script .= "
|
||||
" . $tab . '// ' . $behavior->getName() . " behavior
|
||||
";
|
||||
$script .= preg_replace('/^/m', $tab, $addedScript);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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"
|
||||
* @param string $modifier The name of the modifier object providing the method in the behavior
|
||||
*/
|
||||
public function getBehaviorContentBase($contentName, $modifier)
|
||||
{
|
||||
$modifierGetter = 'get' . $modifier;
|
||||
foreach ($this->getTable()->getBehaviors() as $behavior) {
|
||||
$modifier = $behavior->$modifierGetter();
|
||||
if (method_exists($modifier, $contentName)) {
|
||||
return $modifier->$contentName($this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Use Propel simple templating system to render a PHP file using variables
|
||||
* passed as arguments. The template file name is relative to the behavior's
|
||||
* directory name.
|
||||
*
|
||||
* @param string $filename
|
||||
* @param array $vars
|
||||
* @param string $templateDir
|
||||
* @return string
|
||||
*/
|
||||
public function renderTemplate($filename, $vars = array(), $templateDir = '/templates/')
|
||||
{
|
||||
$filePath = __DIR__ . $templateDir . $filename;
|
||||
if (!file_exists($filePath)) {
|
||||
// try with '.php' at the end
|
||||
$filePath = $filePath . '.php';
|
||||
if (!file_exists($filePath)) {
|
||||
throw new \InvalidArgumentException(sprintf('Template "%s" not found in "%s" directory', $filename, __DIR__ . $templateDir));
|
||||
}
|
||||
}
|
||||
$template = new PropelTemplate();
|
||||
$template->setTemplateFile($filePath);
|
||||
$vars = array_merge($vars, array('behavior' => $this));
|
||||
|
||||
return $template->render($vars);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTableMapClass()
|
||||
{
|
||||
return $this->getStubObjectBuilder()->getUnqualifiedClassName() . 'TableMap';
|
||||
}
|
||||
|
||||
/**
|
||||
* Most of the code comes from the PHP-CS-Fixer project
|
||||
*/
|
||||
private function clean($content)
|
||||
{
|
||||
// trailing whitespaces
|
||||
$content = preg_replace('/[ \t]*$/m', '', $content);
|
||||
|
||||
// indentation
|
||||
$content = preg_replace_callback('/^([ \t]+)/m', function ($matches) use ($content) {
|
||||
return str_replace("\t", ' ', $matches[0]);
|
||||
}, $content);
|
||||
|
||||
// line feed
|
||||
$content = str_replace("\r\n", "\n", $content);
|
||||
|
||||
// Unused "use" statements
|
||||
preg_match_all('/^use (?P<class>[^\s;]+)(?:\s+as\s+(?P<alias>.*))?;/m', $content, $matches, PREG_SET_ORDER);
|
||||
foreach ($matches as $match) {
|
||||
if (isset($match['alias'])) {
|
||||
$short = $match['alias'];
|
||||
} else {
|
||||
$parts = explode('\\', $match['class']);
|
||||
$short = array_pop($parts);
|
||||
}
|
||||
|
||||
preg_match_all('/\b'.$short.'\b/i', str_replace($match[0]."\n", '', $content), $m);
|
||||
if (!count($m[0])) {
|
||||
$content = str_replace($match[0]."\n", '', $content);
|
||||
}
|
||||
}
|
||||
|
||||
// end of line
|
||||
if (strlen($content) && "\n" != substr($content, -1)) {
|
||||
$content = $content."\n";
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens class.
|
||||
*
|
||||
* @param string &$script
|
||||
*/
|
||||
abstract protected function addClassOpen(&$script);
|
||||
|
||||
/**
|
||||
* This method adds the contents of the generated class to the script.
|
||||
*
|
||||
* This method is abstract and should be overridden by the subclasses.
|
||||
*
|
||||
* Hint: Override this method in your subclass if you want to reorganize or
|
||||
* drastically change the contents of the generated object class.
|
||||
*
|
||||
* @param string &$script The script will be modified in this method.
|
||||
*/
|
||||
abstract protected function addClassBody(&$script);
|
||||
|
||||
/**
|
||||
* Closes class.
|
||||
*
|
||||
* @param string &$script
|
||||
*/
|
||||
abstract protected function addClassClose(&$script);
|
||||
}
|
||||
183
core/vendor/propel/propel/src/Propel/Generator/Builder/Om/AbstractObjectBuilder.php
vendored
Normal file
183
core/vendor/propel/propel/src/Propel/Generator/Builder/Om/AbstractObjectBuilder.php
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
<?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\PropelTypes;
|
||||
|
||||
/**
|
||||
* Base class for object-building classes.
|
||||
*
|
||||
* This class is designed so that it can be extended the "standard" ObjectBuilder
|
||||
* and ComplexOMObjectBuilder. Hence, this class should not have any actual
|
||||
* template code in it -- simply basic logic & utility methods.
|
||||
*
|
||||
* @author Hans Lellelid <hans@xmpl.org>
|
||||
*/
|
||||
abstract class AbstractObjectBuilder extends AbstractOMBuilder
|
||||
{
|
||||
/**
|
||||
* Adds the getter methods for the column values.
|
||||
* This is here because it is probably generic enough to apply to templates being generated
|
||||
* in different languages (e.g. PHP4 and PHP5).
|
||||
* @param string &$script The script will be modified in this method.
|
||||
*/
|
||||
protected function addColumnAccessorMethods(&$script)
|
||||
{
|
||||
$table = $this->getTable();
|
||||
|
||||
foreach ($table->getColumns() as $col) {
|
||||
|
||||
// if they're not using the DateTime class than we will generate "compatibility" accessor method
|
||||
if (PropelTypes::DATE === $col->getType()
|
||||
|| PropelTypes::TIME === $col->getType()
|
||||
|| PropelTypes::TIMESTAMP === $col->getType()
|
||||
) {
|
||||
$this->addTemporalAccessor($script, $col);
|
||||
} elseif (PropelTypes::OBJECT === $col->getType()) {
|
||||
$this->addObjectAccessor($script, $col);
|
||||
} elseif (PropelTypes::PHP_ARRAY === $col->getType()) {
|
||||
$this->addArrayAccessor($script, $col);
|
||||
if ($col->isNamePlural()) {
|
||||
$this->addHasArrayElement($script, $col);
|
||||
}
|
||||
} elseif ($col->isEnumType()) {
|
||||
$this->addEnumAccessor($script, $col);
|
||||
} else {
|
||||
$this->addDefaultAccessor($script, $col);
|
||||
}
|
||||
|
||||
if ($col->isLazyLoad()) {
|
||||
$this->addLazyLoader($script, $col);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the mutator (setter) methods for setting column values.
|
||||
* This is here because it is probably generic enough to apply to templates being generated
|
||||
* in different languages (e.g. PHP4 and PHP5).
|
||||
* @param string &$script The script will be modified in this method.
|
||||
*/
|
||||
protected function addColumnMutatorMethods(&$script)
|
||||
{
|
||||
foreach ($this->getTable()->getColumns() as $col) {
|
||||
if ($col->isLobType()) {
|
||||
$this->addLobMutator($script, $col);
|
||||
} elseif (
|
||||
PropelTypes::DATE === $col->getType()
|
||||
|| PropelTypes::TIME === $col->getType()
|
||||
|| PropelTypes::TIMESTAMP === $col->getType()
|
||||
) {
|
||||
$this->addTemporalMutator($script, $col);
|
||||
} elseif (PropelTypes::OBJECT === $col->getType()) {
|
||||
$this->addObjectMutator($script, $col);
|
||||
} elseif (PropelTypes::PHP_ARRAY === $col->getType()) {
|
||||
$this->addArrayMutator($script, $col);
|
||||
if ($col->isNamePlural()) {
|
||||
$this->addAddArrayElement($script, $col);
|
||||
$this->addRemoveArrayElement($script, $col);
|
||||
}
|
||||
} elseif ($col->isEnumType()) {
|
||||
$this->addEnumMutator($script, $col);
|
||||
} elseif ($col->isBooleanType()) {
|
||||
$this->addBooleanMutator($script, $col);
|
||||
} else {
|
||||
$this->addDefaultMutator($script, $col);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the baseClass path if specified for table/db.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getBaseClass()
|
||||
{
|
||||
return $this->getTable()->getBaseClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the interface path if specified for current table.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getInterface()
|
||||
{
|
||||
return $this->getTable()->getInterface();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to add the generic mutator methods (setByName(), setByPosition(), fromArray()).
|
||||
* This is based on the build property propel.addGenericMutators, and also whether the
|
||||
* table is read-only or an alias.
|
||||
*/
|
||||
protected function isAddGenericMutators()
|
||||
{
|
||||
$table = $this->getTable();
|
||||
|
||||
return (!$table->isAlias() && $this->getBuildProperty('addGenericMutators') && !$table->isReadOnly());
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to add the generic accessor methods (getByName(), getByPosition(), toArray()).
|
||||
* This is based on the build property propel.addGenericAccessors, and also whether the
|
||||
* table is an alias.
|
||||
*/
|
||||
protected function isAddGenericAccessors()
|
||||
{
|
||||
$table = $this->getTable();
|
||||
|
||||
return (!$table->isAlias() && $this->getBuildProperty('addGenericAccessors'));
|
||||
}
|
||||
|
||||
protected function hasDefaultValues()
|
||||
{
|
||||
foreach ($this->getTable()->getColumns() as $col) {
|
||||
if (null !== $col->getDefaultValue()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, 'ObjectBuilderModifier');
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 = " ")
|
||||
{
|
||||
return $this->applyBehaviorModifierBase($hookName, 'ObjectBuilderModifier', $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, 'ObjectBuilderModifier');
|
||||
}
|
||||
}
|
||||
124
core/vendor/propel/propel/src/Propel/Generator/Builder/Om/ClassTools.php
vendored
Normal file
124
core/vendor/propel/propel/src/Propel/Generator/Builder/Om/ClassTools.php
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
<?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\Table;
|
||||
|
||||
/**
|
||||
* Tools to support class & package inclusion and referencing.
|
||||
*
|
||||
* @author Hans Lellelid <hans@xmpl.org>
|
||||
*/
|
||||
class ClassTools
|
||||
{
|
||||
|
||||
/**
|
||||
* Gets just classname, given a dot-path to class.
|
||||
* @param string $qualifiedName
|
||||
* @return string
|
||||
*/
|
||||
public static function classname($qualifiedName)
|
||||
{
|
||||
if (false !== $pos = strrpos($qualifiedName, '.')) {
|
||||
return substr($qualifiedName, $pos + 1); // start just after '.'
|
||||
} elseif (false !== $pos = strrpos($qualifiedName, '\\')) {
|
||||
return substr($qualifiedName, $pos + 1);
|
||||
} else {
|
||||
return $qualifiedName; // there is no '.' in the qualified name
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the path to be used in include()/require() statement.
|
||||
*
|
||||
* Supports multiple function signatures:
|
||||
*
|
||||
* (1) getFilePath($dotPathClass);
|
||||
* (2) getFilePath($dotPathPrefix, $className);
|
||||
* (3) getFilePath($dotPathPrefix, $className, $extension);
|
||||
*
|
||||
* @param string $path dot-path to class or to package prefix.
|
||||
* @param string $classname class name
|
||||
* @param string $extension The extension to use on the file.
|
||||
* @return string The constructed file path.
|
||||
*/
|
||||
public static function getFilePath($path, $classname = null, $extension = '.php')
|
||||
{
|
||||
$path = strtr(ltrim($path, '.'), '.', '/');
|
||||
|
||||
return self::createFilePath($path, $classname, $extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method replaces the `getFilePath()` method in OMBuilder as we consider `$path` as
|
||||
* a real path instead of a dot-notation value. `$path` is generated by the `getPackagePath()`
|
||||
* method.
|
||||
*
|
||||
* @param string $path path to class or to package prefix.
|
||||
* @param string $classname class name
|
||||
* @param string $extension The extension to use on the file.
|
||||
* @return string The constructed file path.
|
||||
*/
|
||||
public static function createFilePath($path, $classname = null, $extension = '.php')
|
||||
{
|
||||
if (null === $classname) {
|
||||
return $path . $extension;
|
||||
}
|
||||
|
||||
if (!empty($path)) {
|
||||
$path .= '/';
|
||||
}
|
||||
|
||||
return $path . $classname . $extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the baseClass path if specified for table/db.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getBaseClass(Table $table)
|
||||
{
|
||||
return $table->getBaseClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the interface path if specified for table.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getInterface(Table $table)
|
||||
{
|
||||
return $table->getInterface();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of PHP reserved words.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function getPhpReservedWords()
|
||||
{
|
||||
return array(
|
||||
'and', 'or', 'xor', 'exception', '__FILE__', '__LINE__',
|
||||
'array', 'as', 'break', 'case', 'class', 'const', 'continue',
|
||||
'declare', 'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty',
|
||||
'enddeclare', 'endfor', 'endforeach', 'endif', 'endswitch', 'endwhile',
|
||||
'eval', 'exit', 'extends', 'for', 'foreach', 'function', 'global',
|
||||
'if', 'include', 'include_once', 'isset', 'list', 'new', 'print', 'require',
|
||||
'require_once', 'return', 'static', 'switch', 'unset', 'use', 'var', 'while',
|
||||
'__FUNCTION__', '__CLASS__', '__METHOD__', '__DIR__', '__NAMESPACE__', 'final', 'php_user_filter', 'interface',
|
||||
'implements', 'extends', 'public', 'protected', 'private', 'abstract', 'clone', 'try', 'catch',
|
||||
'throw', 'this', 'namespace'
|
||||
);
|
||||
}
|
||||
}
|
||||
95
core/vendor/propel/propel/src/Propel/Generator/Builder/Om/ExtensionObjectBuilder.php
vendored
Normal file
95
core/vendor/propel/propel/src/Propel/Generator/Builder/Om/ExtensionObjectBuilder.php
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Generates the empty PHP5 stub object class for user object model (OM).
|
||||
*
|
||||
* This class produces the empty stub class that can be customized with application
|
||||
* business logic, custom behavior, etc.
|
||||
*
|
||||
* @author Hans Lellelid <hans@xmpl.org>
|
||||
*/
|
||||
class ExtensionObjectBuilder extends AbstractObjectBuilder
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the name of the current class being built.
|
||||
* @return string
|
||||
*/
|
||||
public function getUnprefixedClassName()
|
||||
{
|
||||
return $this->getTable()->getPhpName();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
$baseClassName = $this->getClassNameFromBuilder($this->getObjectBuilder());
|
||||
|
||||
if ($this->getBuildProperty('addClassLevelComment')) {
|
||||
$script .= "
|
||||
|
||||
/**
|
||||
* Skeleton subclass for representing a row from the '$tableName' table.
|
||||
*
|
||||
* $tableDesc
|
||||
*";
|
||||
if ($this->getBuildProperty('addTimeStamp')) {
|
||||
$now = strftime('%c');
|
||||
$script .= "
|
||||
* This class was autogenerated by Propel " . $this->getBuildProperty('version') . " on:
|
||||
*
|
||||
* $now
|
||||
*";
|
||||
}
|
||||
$script .= "
|
||||
* You should add additional methods to this class to meet the
|
||||
* application requirements. This class will only be generated as
|
||||
* long as it does not already exist in the output directory.
|
||||
*
|
||||
*/";
|
||||
}
|
||||
$script .= PHP_EOL . ($table->isAbstract() ? "abstract " : "")."class ".$this->getUnqualifiedClassName()." extends $baseClassName
|
||||
{
|
||||
";
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the methods that are added as part of the stub object class.
|
||||
*
|
||||
* By default there are no methods for the empty stub classes; override this method
|
||||
* if you want to change that behavior.
|
||||
*
|
||||
* @see ObjectBuilder::addClassBody()
|
||||
*/
|
||||
protected function addClassBody(&$script)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes class.
|
||||
* @param string &$script The script will be modified in this method.
|
||||
*/
|
||||
protected function addClassClose(&$script)
|
||||
{
|
||||
$script .= "
|
||||
}
|
||||
";
|
||||
$this->applyBehaviorModifier('extensionObjectFilter', $script, "");
|
||||
}
|
||||
}
|
||||
125
core/vendor/propel/propel/src/Propel/Generator/Builder/Om/ExtensionQueryBuilder.php
vendored
Normal file
125
core/vendor/propel/propel/src/Propel/Generator/Builder/Om/ExtensionQueryBuilder.php
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Generates the empty PHP5 stub class for object query
|
||||
*
|
||||
* This class produces the empty stub class that can be customized with application
|
||||
* business logic, custom behavior, etc.
|
||||
*
|
||||
* @author Francois Zaninotto
|
||||
*/
|
||||
class ExtensionQueryBuilder extends AbstractOMBuilder
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the name of the current class being built.
|
||||
* @return string
|
||||
*/
|
||||
public function getUnprefixedClassName()
|
||||
{
|
||||
return $this->getTable()->getPhpName() . 'Query';
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
$baseClassName = $this->getClassNameFromBuilder($this->getQueryBuilder());
|
||||
|
||||
$script .= "
|
||||
|
||||
/**
|
||||
* Skeleton subclass for performing query and update operations on the '$tableName' table.
|
||||
*
|
||||
* $tableDesc
|
||||
*";
|
||||
if ($this->getBuildProperty('addTimeStamp')) {
|
||||
$now = strftime('%c');
|
||||
$script .= "
|
||||
* This class was autogenerated by Propel " . $this->getBuildProperty('version') . " on:
|
||||
*
|
||||
* $now
|
||||
*";
|
||||
}
|
||||
$script .= "
|
||||
* You should add additional methods to this class to meet the
|
||||
* application requirements. This class will only be generated as
|
||||
* long as it does not already exist in the output directory.
|
||||
*
|
||||
*/
|
||||
class ".$this->getUnqualifiedClassName()." extends $baseClassName
|
||||
{
|
||||
";
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the methods that are added as part of the stub query class.
|
||||
*
|
||||
* By default there are no methods for the empty stub classes; override this method
|
||||
* if you want to change that behavior.
|
||||
*
|
||||
* @see QueryBuilder::addClassBody()
|
||||
*/
|
||||
|
||||
protected function addClassBody(&$script)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes class.
|
||||
* @param string &$script The script will be modified in this method.
|
||||
*/
|
||||
protected function addClassClose(&$script)
|
||||
{
|
||||
$script .= "
|
||||
} // " . $this->getUnqualifiedClassName() . "
|
||||
";
|
||||
$this->applyBehaviorModifier('extensionQueryFilter', $script, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @param string $tab
|
||||
*/
|
||||
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');
|
||||
}
|
||||
|
||||
}
|
||||
142
core/vendor/propel/propel/src/Propel/Generator/Builder/Om/ExtensionQueryInheritanceBuilder.php
vendored
Normal file
142
core/vendor/propel/propel/src/Propel/Generator/Builder/Om/ExtensionQueryInheritanceBuilder.php
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
<?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\Inheritance;
|
||||
use Propel\Generator\Exception\BuildException;
|
||||
|
||||
/**
|
||||
* Generates the empty PHP5 stub query class for use with single table inheritance.
|
||||
*
|
||||
* This class produces the empty stub class that can be customized with
|
||||
* application business logic, custom behavior, etc.
|
||||
*
|
||||
* @author François Zaninotto
|
||||
*/
|
||||
class ExtensionQueryInheritanceBuilder extends AbstractOMBuilder
|
||||
{
|
||||
/**
|
||||
* The current child "object" we are operating on.
|
||||
*
|
||||
*/
|
||||
protected $child;
|
||||
|
||||
/**
|
||||
* Returns the name of the current class being built.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUnprefixedClassName()
|
||||
{
|
||||
return $this->getChild()->getClassName() . 'Query';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the package for the [base] object classes.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPackage()
|
||||
{
|
||||
return ($this->getChild()->getPackage() ? $this->getChild()->getPackage() : parent::getPackage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the child object that we're operating on currently.
|
||||
*
|
||||
* @param Inheritance $child Inheritance
|
||||
*/
|
||||
public function setChild(Inheritance $child)
|
||||
{
|
||||
$this->child = $child;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the child object we're operating on currently.
|
||||
*
|
||||
* @return Inheritance
|
||||
* @throws BuildException
|
||||
*/
|
||||
public function getChild()
|
||||
{
|
||||
if (!$this->child) {
|
||||
throw new BuildException("The MultiExtendObjectBuilder needs to be told which child class to build (via setChild() method) before it can build the stub class.");
|
||||
}
|
||||
|
||||
return $this->child;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds class phpdoc comment and opening of class.
|
||||
*
|
||||
* @param string $script
|
||||
*/
|
||||
protected function addClassOpen(&$script)
|
||||
{
|
||||
$table = $this->getTable();
|
||||
$tableName = $table->getName();
|
||||
$tableDesc = $table->getDescription();
|
||||
|
||||
$baseBuilder = $this->getNewQueryInheritanceBuilder($this->getChild());
|
||||
$baseClassName = $this->getClassNameFromBuilder($baseBuilder);
|
||||
|
||||
$script .= "
|
||||
|
||||
/**
|
||||
* Skeleton subclass for representing a query for one of the subclasses of the '$tableName' table.
|
||||
*
|
||||
* $tableDesc
|
||||
*";
|
||||
if ($this->getBuildProperty('addTimeStamp')) {
|
||||
$now = strftime('%c');
|
||||
$script .= "
|
||||
* This class was autogenerated by Propel " . $this->getBuildProperty('version') . " on:
|
||||
*
|
||||
* $now
|
||||
*";
|
||||
}
|
||||
$script .= "
|
||||
* You should add additional methods to this class to meet the
|
||||
* application requirements. This class will only be generated as
|
||||
* long as it does not already exist in the output directory.
|
||||
*
|
||||
*/
|
||||
class " .$this->getUnqualifiedClassName() . " extends " . $baseClassName . "
|
||||
{
|
||||
";
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the methods that are added as part of the stub object class.
|
||||
*
|
||||
* By default there are no methods for the empty stub classes; override this method
|
||||
* if you want to change that behavior.
|
||||
*
|
||||
* @param string $script
|
||||
* @see ObjectBuilder::addClassBody()
|
||||
*/
|
||||
protected function addClassBody(&$script)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes class.
|
||||
*
|
||||
* @param string $script
|
||||
*/
|
||||
protected function addClassClose(&$script)
|
||||
{
|
||||
$script .= "
|
||||
} // " . $this->getUnqualifiedClassName() . "
|
||||
";
|
||||
}
|
||||
}
|
||||
93
core/vendor/propel/propel/src/Propel/Generator/Builder/Om/InterfaceBuilder.php
vendored
Normal file
93
core/vendor/propel/propel/src/Propel/Generator/Builder/Om/InterfaceBuilder.php
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Generates the empty PHP5 stub interface for user object model (OM).
|
||||
*
|
||||
* This class produces the empty stub interface when the interface="" attribute is used
|
||||
* in the the schema xml.
|
||||
*
|
||||
* @author Hans Lellelid <hans@xmpl.org>
|
||||
*/
|
||||
class InterfaceBuilder extends AbstractObjectBuilder
|
||||
{
|
||||
/**
|
||||
* Returns the name of the current class being built.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUnprefixedClassName()
|
||||
{
|
||||
return ClassTools::classname($this->getInterface());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
$script .= "
|
||||
/**
|
||||
* This is an interface that should be filled with the public api of the $tableName objects.
|
||||
*
|
||||
* $tableDesc
|
||||
*";
|
||||
if ($this->getBuildProperty('addTimeStamp')) {
|
||||
$now = strftime('%c');
|
||||
$script .= "
|
||||
* This class was autogenerated by Propel " . $this->getBuildProperty('version') . " on:
|
||||
*
|
||||
* $now
|
||||
*";
|
||||
}
|
||||
$script .= "
|
||||
* You should add additional method declarations to this interface to meet the
|
||||
* application requirements. This interface will only be generated as
|
||||
* long as it does not already exist in the output directory.
|
||||
*
|
||||
*/
|
||||
interface ".$this->getUnqualifiedClassName()."
|
||||
{
|
||||
";
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the methods that are added as part of the stub object class.
|
||||
*
|
||||
* By default there are no methods for the empty stub classes; override this method
|
||||
* if you want to change that behavior.
|
||||
*
|
||||
* @see ObjectBuilder::addClassBody()
|
||||
*/
|
||||
protected function addClassBody(&$script)
|
||||
{
|
||||
// there is no class body
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes class.
|
||||
* @param string &$script The script will be modified in this method.
|
||||
*/
|
||||
protected function addClassClose(&$script)
|
||||
{
|
||||
$script .= "
|
||||
} // " . $this->getUnqualifiedClassName() . "
|
||||
";
|
||||
}
|
||||
|
||||
} // ExtensionObjectBuilder
|
||||
200
core/vendor/propel/propel/src/Propel/Generator/Builder/Om/MultiExtendObjectBuilder.php
vendored
Normal file
200
core/vendor/propel/propel/src/Propel/Generator/Builder/Om/MultiExtendObjectBuilder.php
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
<?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\Exception\BuildException;
|
||||
use Propel\Generator\Model\Inheritance;
|
||||
|
||||
/**
|
||||
* Generates the empty PHP5 stub object class for use with inheritance in the
|
||||
* user object model (OM).
|
||||
*
|
||||
* This class produces the empty stub class that can be customized with
|
||||
* application business logic, custom behavior, etc.
|
||||
*
|
||||
* @author Hans Lellelid <hans@xmpl.org>
|
||||
*/
|
||||
class MultiExtendObjectBuilder extends AbstractObjectBuilder
|
||||
{
|
||||
/**
|
||||
* The current child "object" we are operating on.
|
||||
*
|
||||
*/
|
||||
private $child;
|
||||
|
||||
/**
|
||||
* Returns the name of the current class being built.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUnprefixedClassName()
|
||||
{
|
||||
return $this->getChild()->getClassName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides method to return child package, if specified.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPackage()
|
||||
{
|
||||
return ($this->child->getPackage() ? $this->child->getPackage() : parent::getPackage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the child object that we're operating on currently.
|
||||
*
|
||||
* @param Inheritance $child Inheritance
|
||||
*/
|
||||
public function setChild(Inheritance $child)
|
||||
{
|
||||
$this->child = $child;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the child object we're operating on currently.
|
||||
*
|
||||
* @return Inheritance
|
||||
* @throws BuildException
|
||||
*/
|
||||
public function getChild()
|
||||
{
|
||||
if (!$this->child) {
|
||||
throw new BuildException("The MultiExtendObjectBuilder needs to be told which child class to build (via setChild() method) before it can build the stub class.");
|
||||
}
|
||||
|
||||
return $this->child;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns classpath to parent class.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getParentClasspath()
|
||||
{
|
||||
if ($this->getChild()->getAncestor()) {
|
||||
return $this->getChild()->getAncestor();
|
||||
}
|
||||
|
||||
return $this->getObjectBuilder()->getClasspath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns classname of parent class.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getParentClassName()
|
||||
{
|
||||
return ClassTools::classname($this->getParentClasspath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the file path to the parent class.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getParentClassFilePath()
|
||||
{
|
||||
return ClassTools::getFilePath($this->getParentClasspath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds class phpdoc comment and opening of class.
|
||||
*
|
||||
* @param string &$script
|
||||
*/
|
||||
protected function addClassOpen(&$script)
|
||||
{
|
||||
if ($this->getChild()->getAncestor()) {
|
||||
$ancestorClassName = $this->getChild()->getAncestor();
|
||||
if ($this->getDatabase()->hasTableByPhpName($ancestorClassName)) {
|
||||
$this->declareClassFromBuilder($this->getNewStubObjectBuilder($this->getDatabase()->getTableByPhpName($ancestorClassName)));
|
||||
} else {
|
||||
$this->declareClassNamespace($ancestorClassName, $this->getNamespace());
|
||||
}
|
||||
} else {
|
||||
$this->declareClassFromBuilder($this->getObjectBuilder());
|
||||
}
|
||||
$table = $this->getTable();
|
||||
$tableName = $table->getName();
|
||||
$tableDesc = $table->getDescription();
|
||||
|
||||
$script .= "
|
||||
|
||||
/**
|
||||
* Skeleton subclass for representing a row from one of the subclasses of the '$tableName' table.
|
||||
*
|
||||
* $tableDesc
|
||||
*";
|
||||
if ($this->getBuildProperty('addTimeStamp')) {
|
||||
$now = strftime('%c');
|
||||
$script .= "
|
||||
* This class was autogenerated by Propel " . $this->getBuildProperty('version') . " on:
|
||||
*
|
||||
* $now
|
||||
*";
|
||||
}
|
||||
$script .= "
|
||||
* You should add additional methods to this class to meet the
|
||||
* application requirements. This class will only be generated as
|
||||
* long as it does not already exist in the output directory.
|
||||
*
|
||||
*/
|
||||
class ".$this->getUnqualifiedClassName()." extends ".$this->getParentClassName()."
|
||||
{
|
||||
";
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the methods that are added as part of the stub object class.
|
||||
*
|
||||
* By default there are no methods for the empty stub classes; override this
|
||||
* method if you want to change that behavior.
|
||||
*
|
||||
* @param string &$script
|
||||
* @see ObjectBuilder::addClassBody()
|
||||
*/
|
||||
protected function addClassBody(&$script)
|
||||
{
|
||||
$child = $this->getChild();
|
||||
$col = $child->getColumn();
|
||||
$cfc = $col->getPhpName();
|
||||
|
||||
$const = "CLASSKEY_".strtoupper($child->getKey());
|
||||
|
||||
$script .= "
|
||||
/**
|
||||
* Constructs a new ".$this->getChild()->getClassName()." class, setting the ".$col->getName()." column to ".$this->getTableMapClassName()."::$const.
|
||||
*/
|
||||
public function __construct()
|
||||
{";
|
||||
$script .= "
|
||||
parent::__construct();
|
||||
\$this->set$cfc(".$this->getTableMapClassName()."::CLASSKEY_".strtoupper($child->getKey()).");
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes class.
|
||||
*
|
||||
* @param string &$script
|
||||
*/
|
||||
protected function addClassClose(&$script)
|
||||
{
|
||||
$script .= "
|
||||
} // " . $this->getUnqualifiedClassName() . "
|
||||
";
|
||||
}
|
||||
}
|
||||
5280
core/vendor/propel/propel/src/Propel/Generator/Builder/Om/ObjectBuilder.php
vendored
Normal file
5280
core/vendor/propel/propel/src/Propel/Generator/Builder/Om/ObjectBuilder.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user