sintonia/airtime_mvc/library/doctrine/migrations/doctrine-migrations.phar

28018 lines
864 KiB
Plaintext
Raw Normal View History

<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
Phar::mapPhar();
require_once 'phar://'.__FILE__.'/Doctrine/Common/ClassLoader.php';
$classLoader = new \Doctrine\Common\ClassLoader('Doctrine\Common', 'phar://'.__FILE__);
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Doctrine\DBAL', 'phar://'.__FILE__);
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Symfony', 'phar://'.__FILE__);
$classLoader->register();
$helperSet = new \Symfony\Component\Console\Helper\HelperSet(array(
'dialog' => new \Symfony\Component\Console\Helper\DialogHelper(),
));
$cli = new \Symfony\Component\Console\Application('Doctrine Migrations', \Doctrine\DBAL\Migrations\MigrationsVersion::VERSION);
$cli->setCatchExceptions(true);
$cli->setHelperSet($helperSet);
$cli->addCommands(array(
// Migrations Commands
new \Doctrine\DBAL\Migrations\Tools\Console\Command\DiffCommand(),
new \Doctrine\DBAL\Migrations\Tools\Console\Command\ExecuteCommand(),
new \Doctrine\DBAL\Migrations\Tools\Console\Command\GenerateCommand(),
new \Doctrine\DBAL\Migrations\Tools\Console\Command\MigrateCommand(),
new \Doctrine\DBAL\Migrations\Tools\Console\Command\StatusCommand(),
new \Doctrine\DBAL\Migrations\Tools\Console\Command\VersionCommand()
));
$input = file_exists('migrations-input.php')
? include('migrations-input.php')
: null;
$output = file_exists('migrations-output.php')
? include('migrations-output.php')
: null;
$cli->run($input, $output);
__HALT_COMPILER(); ?>
<EFBFBD>,<00>;Doctrine/DBAL/Migrations/IrreversibleMigrationException.php<68><00><><EFBFBD>L<EFBFBD><00><><EFBFBD>ܶ4Doctrine/DBAL/Migrations/AbortMigrationException.phpm<00><><EFBFBD>Lm<00><><0E><>3Doctrine/DBAL/Migrations/SkipMigrationException.phpl<00><><EFBFBD>Ll.Doctrine/DBAL/Migrations/AbstractMigration.php<68><00><><EFBFBD>L<EFBFBD><00><><EFBFBD>`<60>/Doctrine/DBAL/Migrations/MigrationException.php<68> <00><><EFBFBD>L<EFBFBD> (Shz<68>&Doctrine/DBAL/Migrations/Migration.php<68><00><><EFBFBD>L<EFBFBD><00>~<7E><><EFBFBD>8Doctrine/DBAL/Migrations/Configuration/Configuration.php"7<00><><EFBFBD>L"7p됶;Doctrine/DBAL/Migrations/Configuration/XmlConfiguration.php<68> <00><><EFBFBD>L<EFBFBD> <00>Z<EFBFBD><1D><Doctrine/DBAL/Migrations/Configuration/YamlConfiguration.php<68> <00><><EFBFBD>L<EFBFBD> >x7<78><37>DDoctrine/DBAL/Migrations/Configuration/AbstractFileConfiguration.php<68> <00><><EFBFBD>L<EFBFBD> <00>M<EFBFBD><17>)Doctrine/DBAL/Migrations/OutputWriter.php<00><><EFBFBD>L4<><34>4<EFBFBD>$Doctrine/DBAL/Migrations/Version.php<68>&<00><><EFBFBD>L<EFBFBD>&v<>M}<7D>.Doctrine/DBAL/Migrations/MigrationsVersion.php8<00><><EFBFBD>L8<00>R<><52>>Doctrine/DBAL/Migrations/Tools/Console/Command/DiffCommand.php<68><00><><EFBFBD>L<EFBFBD><00>4&<16>BDoctrine/DBAL/Migrations/Tools/Console/Command/AbstractCommand.php<68><00><><EFBFBD>L<EFBFBD>*T\j<>BDoctrine/DBAL/Migrations/Tools/Console/Command/GenerateCommand.php<68><00><><EFBFBD>L<EFBFBD>~<7E><1A>ADoctrine/DBAL/Migrations/Tools/Console/Command/VersionCommand.php<00><><EFBFBD>L<00><><13><>ADoctrine/DBAL/Migrations/Tools/Console/Command/ExecuteCommand.php<68><00><><EFBFBD>L<EFBFBD>U<11>I<EFBFBD>@Doctrine/DBAL/Migrations/Tools/Console/Command/StatusCommand.php<68><00><><EFBFBD>L<EFBFBD><00>e<EFBFBD>-<2D>ADoctrine/DBAL/Migrations/Tools/Console/Command/MigrateCommand.php7<00><><EFBFBD>L7a<>Doctrine/DBAL/DBALException.php
<00><><EFBFBD>L
<00>^<5E><<3C>)Doctrine/DBAL/Driver/PDOOracle/Driver.php<68>
<00><><EFBFBD>L<EFBFBD>
<00><>s&<26>-Doctrine/DBAL/Driver/IBMDB2/DB2Connection.php <00><><EFBFBD>L <t<><00>,Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php<68>.<00><><EFBFBD>L<EFBFBD>.<00><1B>3<EFBFBD>,Doctrine/DBAL/Driver/IBMDB2/DB2Exception.php7<00><><EFBFBD>L7<00>~<7E><><EFBFBD>)Doctrine/DBAL/Driver/IBMDB2/DB2Driver.php<68><00><><EFBFBD>L<EFBFBD><00>h<EFBFBD>$<24>%Doctrine/DBAL/Driver/PDOStatement.php <00><><EFBFBD>L <00>F<17><>(Doctrine/DBAL/Driver/PDOMsSql/Driver.php<68> <00><><EFBFBD>L<EFBFBD> <00>kX)<29>,Doctrine/DBAL/Driver/PDOMsSql/Connection.php|<00><><EFBFBD>L|P{1<13>"Doctrine/DBAL/Driver/Statement.php<68>%<00><><EFBFBD>L<EFBFBD>%,<2C>i<EFBFBD><69>(Doctrine/DBAL/Driver/PDOPgSql/Driver.php<68><00><><EFBFBD>L<EFBFBD><00><EFBFBD>Z<EFBFBD>&Doctrine/DBAL/Driver/PDOConnection.php<00><><EFBFBD>LQ0Զ&Doctrine/DBAL/Driver/PDOIbm/Driver.phpN<00><><EFBFBD>LNSPuo<75>(Doctrine/DBAL/Driver/PDOMySql/Driver.php? <00><><EFBFBD>L? <00><><EFBFBD><EFBFBD><EFBFBD>)Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php<68> <00><><EFBFBD>L<EFBFBD> <00>ܪ<>)Doctrine/DBAL/Driver/PDOSqlite/Driver.php<68><00><><EFBFBD>L<EFBFBD><00><>V<EFBFBD><56>+Doctrine/DBAL/Driver/OCI8/OCI8Exception.php<68><00><><EFBFBD>L<EFBFBD>J<>ٮ<EFBFBD>$Doctrine/DBAL/Driver/OCI8/Driver.php? <00><><EFBFBD>L? <00><0F><><EFBFBD>+Doctrine/DBAL/Driver/OCI8/OCI8Statement.php<00><><EFBFBD>L<00>R<14><>,Doctrine/DBAL/Driver/OCI8/OCI8Connection.php<00><><EFBFBD>L<00><><EFBFBD><13>#Doctrine/DBAL/Driver/Connection.php<68><00><><EFBFBD>L<EFBFBD><00>kV<6B><56>Doctrine/DBAL/Events.php<68><00><><EFBFBD>L<EFBFBD><00>p<13>Doctrine/DBAL/DriverManager.php<68><00><><EFBFBD>L<EFBFBD>d<>< <09>Doctrine/DBAL/Configuration.phpp<00><><EFBFBD>Lp<00><>Mo<4D>Doctrine/DBAL/Statement.php<00><><EFBFBD>Lu<><75>۶+Doctrine/DBAL/Schema/MySqlSchemaManager.php:<00><><EFBFBD>L:#<23>r<EFBFBD><72>0Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php<68>$<00><><EFBFBD>L<EFBFBD>$<00>ۋ<EFBFBD><DB8B>Doctrine/DBAL/Schema/View.phpF<00><><EFBFBD>LF<00>.<2E><><EFBFBD>)Doctrine/DBAL/Schema/DB2SchemaManager.php=<00><><EFBFBD>L=ӓ<17><>,Doctrine/DBAL/Schema/SqliteSchemaManager.php<68><00><><EFBFBD>L<EFBFBD>U<7F><55>#Doctrine/DBAL/Schema/Comparator.php<68>3<00><><EFBFBD>L<EFBFBD>3<00><><EFBFBD>
<EFBFBD>Doctrine/DBAL/Schema/Index.php<68><00><><EFBFBD>L<EFBFBD><00>&o!<21>.Doctrine/DBAL/Schema/AbstractSchemaManager.phpKV<00><><EFBFBD>LKV,:<08><>&Doctrine/DBAL/Schema/AbstractAsset.php<68> <00><><EFBFBD>L<EFBFBD> <00>TK<>%Doctrine/DBAL/Schema/SchemaConfig.phpC<00><><EFBFBD>LC<00>><3E>ƶDoctrine/DBAL/Schema/Column.php<68><00><><EFBFBD>L<EFBFBD>+W<><57><EFBFBD>#Doctrine/DBAL/Schema/Constraint.phpO<00><><EFBFBD>LO<00>:<3A><><EFBFBD>#Doctrine/DBAL/Schema/SchemaDiff.php<68><00><><EFBFBD>L<EFBFBD>~'<27>׶Doctrine/DBAL/Schema/Schema.php3"<00><><EFBFBD>L3""$V<>+Doctrine/DBAL/Schema/MsSqlSchemaManager.php!<00><><EFBFBD>L!<00>@ᄶ(Doctrine/DBAL/Schema/Visitor/Visitor.php* <00><><EFBFBD>L* D<>i&<26>9Doctrine/DBAL/Schema/Visitor/CreateSchemaSqlCollector.phpj<00><><EFBFBD>Lj<00><>7Doctrine/DBAL/Schema/Visitor/DropSchemaSqlCollector.php<68><00><><EFBFBD>L<EFBFBD>0<><07><>-Doctrine/DBAL/Schema/ForeignKeyConstraint.php<68><00><><EFBFBD>L<EFBFBD>}<7D>W<EFBFBD><57>Doctrine/DBAL/Schema/Table.php`C<00><><EFBFBD>L`C<06><>P<EFBFBD>"Doctrine/DBAL/Schema/TableDiff.php^<00><><EFBFBD>L^<00><12><>,Doctrine/DBAL/Schema/OracleSchemaManager.php6$<00><><EFBFBD>L6$<00><>G<>!Doctrine/DBAL/Schema/Sequence.php<68><00><><EFBFBD>L<EFBFBD>L<><4C>k<EFBFBD>#Doctrine/DBAL/Schema/ColumnDiff.php<00><><EFBFBD>L<00><>'<27><>(Doctrine/DBAL/Schema/SchemaException.phpt<00><><EFBFBD>Ltή!<21><>Doctrine/DBAL/LockMode.php<68><00><><EFBFBD>L<EFBFBD>jWW̶Doctrine/DBAL/Driver.php=
<00><><EFBFBD>L=
1<1B>]<5D>.Doctrine/DBAL/Platforms/PostgreSqlPlatform.php<68>Y<00><><EFBFBD>L<EFBFBD>Y<00><>v<EFBFBD><76>)Doctrine/DBAL/Platforms/MsSqlPlatform.php<68>M<00><><EFBFBD>L<EFBFBD>M<00><>>0<>*Doctrine/DBAL/Platforms/OraclePlatform.php<68>V<00><><EFBFBD>L<EFBFBD>V|<1F><><EFBFBD>'Doctrine/DBAL/Platforms/DB2Platform.phpA<00><><EFBFBD>LA\E1߶)Doctrine/DBAL/Platforms/MySqlPlatform.php<68>M<00><><EFBFBD>L<EFBFBD>M<00> <09>6<EFBFBD>,Doctrine/DBAL/Platforms/AbstractPlatform.php<68><70><00><><EFBFBD>L<EFBFBD><4C>X<><58><EFBFBD><EFBFBD>*Doctrine/DBAL/Platforms/SqlitePlatform.phpF8<00><><EFBFBD>LF8E T<>Doctrine/DBAL/README.markdown<00><><EFBFBD>L<00>Doctrine/DBAL/Version.php<68><00><><EFBFBD>L<EFBFBD>|!<21><>%Doctrine/DBAL/ConnectionException.php<00><><EFBFBD>L<00><><EFBFBD>C<EFBFBD>Doctrine/DBAL/Connection.php<68>{<00><><EFBFBD>L<EFBFBD>{<00><><EFBFBD><1F>'Doctrine/DBAL/Logging/EchoSQLLogger.phpN<00><><EFBFBD>LN<00>N<><4E>$Doctrine/DBAL/Logging/DebugStack.php<68><00><><EFBFBD>L<EFBFBD>}<02><12>#Doctrine/DBAL/Logging/SQLLogger.php<68><00><><EFBFBD>L<EFBFBD>5<><35> <20>5Doctrine/DBAL/Tools/Console/Command/ImportCommand.php<00><><EFBFBD>LG:<3A><><EFBFBD>5Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php/ <00><><EFBFBD>L/ <00><>9R<39>7Doctrine/DBAL/Tools/Console/Helper/ConnectionHelper.phpv<00><><EFBFBD>Lv4<18>s<EFBFBD>'Doctrine/DBAL/Types/VarDateTimeType.php<68><00><><EFBFBD>L<EFBFBD>w<>3<EFBFBD><33>#Doctrine/DBAL/Types/IntegerType.php<68><00><><EFBFBD>L<EFBFBD> l6<6C><36> Doctrine/DBAL/Types/DateType.php<68><00><><EFBFBD>L<EFBFBD><00>E<EFBFBD>e<EFBFBD>Doctrine/DBAL/Types/Type.php<00><><EFBFBD>L<00>,do<64>!Doctrine/DBAL/Types/FloatType.phpz<00><><EFBFBD>Lz~[e<><65>$Doctrine/DBAL/Types/SmallIntType.php<68><00><><EFBFBD>L<EFBFBD>G9#k<>"Doctrine/DBAL/Types/BigIntType.php<68><00><><EFBFBD>L<EFBFBD>><1E><><EFBFBD>"Doctrine/DBAL/Types/StringType.phpY<00><><EFBFBD>LY(<28>.G<>"Doctrine/DBAL/Types/ObjectType.php<68><00><><EFBFBD>L<EFBFBD>M(<1D>&Doctrine/DBAL/Types/DateTimeTzType.php <00><><EFBFBD>L <00><>}<10>+Doctrine/DBAL/Types/ConversionException.php<68><00><><EFBFBD>L<EFBFBD><00>Gf[<5B>$Doctrine/DBAL/Types/DateTimeType.php<68><00><><EFBFBD>L<EFBFBD><03>݁<EFBFBD>#Doctrine/DBAL/Types/DecimalType.php<00><><EFBFBD>L<00><><07><> Doctrine/DBAL/Types/TextType.php<00><><EFBFBD>L<00><><EFBFBD>@<40>!Doctrine/DBAL/Types/ArrayType.php<68><00><><EFBFBD>L<EFBFBD><00><><EFBFBD><EFBFBD><EFBFBD>#Doctrine/DBAL/Types/BooleanType.php<00><><EFBFBD>L<00><4<><34> Doctrine/DBAL/Types/TimeType.php5<00><><EFBFBD>L5<00>ٻ<11>+Doctrine/DBAL/Event/ConnectionEventArgs.php<68><00><><EFBFBD>L<EFBFBD><01>5<EFBFBD><35>2Doctrine/DBAL/Event/Listeners/MysqlSessionInit.phpO <00><><EFBFBD>LO <00><><EFBFBD>9<EFBFBD>3Doctrine/DBAL/Event/Listeners/OracleSessionInit.php<68> <00><><EFBFBD>L<EFBFBD> 1?<3F><16>Doctrine/Common/EventArgs.php#
<00><><EFBFBD>L#
to<74><07>#Doctrine/Common/CommonException.phpq<00><><EFBFBD>Lq(|k<>0Doctrine/Common/Annotations/AnnotationReader.php"<00><><EFBFBD>L"
6<13><>3Doctrine/Common/Annotations/AnnotationException.php<68><00><><EFBFBD>L<EFBFBD><00>=?<3F><>&Doctrine/Common/Annotations/Parser.php<68>=<00><><EFBFBD>L<EFBFBD>=3<><33>S<EFBFBD>%Doctrine/Common/Annotations/Lexer.php<68><00><><EFBFBD>L<EFBFBD>Sn<53><6E><EFBFBD>*Doctrine/Common/Annotations/Annotation.php<68> <00><><EFBFBD>L<EFBFBD> @<40><><18>Doctrine/Common/ClassLoader.php"<00><><EFBFBD>L"<00>:<3A>@<40>/Doctrine/Common/Collections/ArrayCollection.php<68>.<00><><EFBFBD>L<EFBFBD>.<00>j<1B><>*Doctrine/Common/Collections/Collection.phpZ <00><><EFBFBD>LZ <00><><EFBFBD><EFBFBD><EFBFBD>Doctrine/Common/Version.php<68><00><><EFBFBD>L<EFBFBD><00><>/\<5C>%Doctrine/Common/Cache/XcacheCache.php<68> <00><><EFBFBD>L<EFBFBD> &$Doctrine/Common/Cache/ArrayCache.php' <00><><EFBFBD>L' <00>::b<>'Doctrine/Common/Cache/MemcacheCache.php<68> <00><><EFBFBD>L<EFBFBD> r<>6<EFBFBD><36>Doctrine/Common/Cache/Cache.php
<00><><EFBFBD>L
<00><>\O<>"Doctrine/Common/Cache/ApcCache.phpA <00><><EFBFBD>LA Y<><59>*<2A>'Doctrine/Common/Cache/AbstractCache.php1<00><><EFBFBD>L1L<><4C>0<EFBFBD>Doctrine/Common/Util/Debug.php<00><><EFBFBD>L<00>;<3B>`<60>"Doctrine/Common/Util/Inflector.php;
<00><><EFBFBD>L;
;%됶)Doctrine/Common/NotifyPropertyChanged.php<68><00><><EFBFBD>L<EFBFBD><1A>nF<6E>+Doctrine/Common/PropertyChangedListener.php<68><00><><EFBFBD>L<EFBFBD><00><><EFBFBD><EFBFBD><EFBFBD> Doctrine/Common/EventManager.php,<00><><EFBFBD>L,<00>g]F<>Doctrine/Common/Lexer.phpK<00><><EFBFBD>LKN<><4E><01>#Doctrine/Common/EventSubscriber.php<00><><EFBFBD>LiJ<69><17>Symfony/Component/Yaml/Yaml.php<68> <00><><EFBFBD>L<EFBFBD> !<21><><13>!Symfony/Component/Yaml/Dumper.php<00><><EFBFBD>LÂ<><C382><EFBFBD>*Symfony/Component/Yaml/ParserException.php<00><><EFBFBD>L<00><><EFBFBD>9<EFBFBD>$Symfony/Component/Yaml/Exception.php
<00><><EFBFBD>L
WGQ<47>!Symfony/Component/Yaml/Inline.php<68>*<00><><EFBFBD>L<EFBFBD>*:<3A>ڶ!Symfony/Component/Yaml/Parser.php<68>?<00><><EFBFBD>L<EFBFBD>?<00>|#ɶ1Symfony/Component/Console/Command/ListCommand.php<68><00><><EFBFBD>L<EFBFBD><00>[<5B><><EFBFBD>1Symfony/Component/Console/Command/HelpCommand.phpi<00><><EFBFBD>LiL<>U<EFBFBD><55>-Symfony/Component/Console/Command/Command.phpR8<00><><EFBFBD>LR8<00><>Dj<44>2Symfony/Component/Console/Output/ConsoleOutput.phpi<00><><EFBFBD>Li<00>w*<2A><>4Symfony/Component/Console/Output/OutputInterface.php<68><00><><EFBFBD>L<EFBFBD><00><>w <0A>1Symfony/Component/Console/Output/StreamOutput.php <00><><EFBFBD>L <00><><EFBFBD>J<EFBFBD>+Symfony/Component/Console/Output/Output.php<68><00><><EFBFBD>L<EFBFBD><00>vs <0A>/Symfony/Component/Console/Output/NullOutput.php<68><00><><EFBFBD>L<EFBFBD><00>1<EFBFBD><31><EFBFBD>#Symfony/Component/Console/Shell.php!<00><><EFBFBD>L!ɖ<0E><>4Symfony/Component/Console/Helper/FormatterHelper.php <00><><EFBFBD>L g<><67><EFBFBD>.Symfony/Component/Console/Helper/HelperSet.php <00><><EFBFBD>L <14><>Ƕ+Symfony/Component/Console/Helper/Helper.php<68><00><><EFBFBD>L<EFBFBD><00><10>ܶ4Symfony/Component/Console/Helper/HelperInterface.php<68><00><><EFBFBD>L<EFBFBD><00><>f <0A>1Symfony/Component/Console/Helper/DialogHelper.php<68> <00><><EFBFBD>L<EFBFBD> 3<>)Symfony/Component/Console/Application.php<68>[<00><><EFBFBD>L<EFBFBD>[<00>N<EFBFBD><4E><EFBFBD>6Symfony/Component/Console/Tester/ApplicationTester.phpb
<00><><EFBFBD>Lb
<00><>*<19>2Symfony/Component/Console/Tester/CommandTester.php8
<00><><EFBFBD>L8
<00>ե<EFBFBD><D5A5>)Symfony/Component/Console/Input/Input.php~<00><><EFBFBD>L~)<29><>[<5B>.Symfony/Component/Console/Input/ArrayInput.php <00><><EFBFBD>L <00>glt<6C>/Symfony/Component/Console/Input/InputOption.phpA<00><><EFBFBD>LA<00><><EFBFBD>6<EFBFBD>3Symfony/Component/Console/Input/InputDefinition.phpE<<00><><EFBFBD>LE<<00>.<0F><>2Symfony/Component/Console/Input/InputInterface.php<68><00><><EFBFBD>L<EFBFBD>\<5C>)-<2D>-Symfony/Component/Console/Input/ArgvInput.php<68><00><><EFBFBD>L<EFBFBD><00>M<><4D>/Symfony/Component/Console/Input/StringInput.php<68> <00><><EFBFBD>L<EFBFBD> g<>kd<6B>1Symfony/Component/Console/Input/InputArgument.php<68> <00><><EFBFBD>L<EFBFBD> ]<5D>TP<54><?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Migrations;
/**
* Exception to be thrown in the down() methods of migrations that signifies it
* is an irreversible migration and stops execution.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Jonathan H. Wage <jonwage@gmail.com>
*/
class IrreversibleMigrationException extends \Exception
{
}<?php
namespace Doctrine\DBAL\Migrations;
class AbortMigrationException extends MigrationException
{
}<?php
namespace Doctrine\DBAL\Migrations;
class SkipMigrationException extends MigrationException
{
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Migrations;
use Doctrine\DBAL\Schema\Schema,
Doctrine\DBAL\Migrations\Configuration\Configuration,
Doctrine\DBAL\Migrations\Version;
/**
* Abstract class for individual migrations to extend from.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Jonathan H. Wage <jonwage@gmail.com>
*/
abstract class AbstractMigration
{
/** The Migrations Configuration instance for this migration */
protected $_configuration;
/** The OutputWriter object instance used for outputting information */
protected $_outputWriter;
/** The Doctrine\DBAL\Connection instance we are migrating */
protected $_connection;
/** Reference to the SchemaManager instance referened by $_connection */
protected $_sm;
/** Reference to the DatabasePlatform instance referenced by $_conection */
protected $_platform;
/** Reference to the Version instance representing this migration */
protected $_version;
public function __construct(Version $version)
{
$this->_configuration = $version->getConfiguration();
$this->_outputWriter = $this->_configuration->getOutputWriter();
$this->_connection = $this->_configuration->getConnection();
$this->_sm = $this->_connection->getSchemaManager();
$this->_platform = $this->_connection->getDatabasePlatform();
$this->_version = $version;
}
abstract public function up(Schema $schema);
abstract public function down(Schema $schema);
protected function _addSql($sql)
{
return $this->_version->addSql($sql);
}
protected function _write($message)
{
$this->_outputWriter->write($message);
}
protected function _throwIrreversibleMigrationException($message = null)
{
if ($message === null) {
$message = 'This migration is irreversible and cannot be reverted.';
}
throw new IrreversibleMigrationException($message);
}
/**
* Print a warning message if the condition evalutes to TRUE.
*
* @param bool $condition
* @param string $message
*/
public function warnIf($condition, $message = '')
{
$message = (strlen($message)) ? $message : 'Unknown Reason';
if ($condition === true) {
$this->_outputWriter->write(' <warning>Warning during ' . $this->_version->getExecutionState() . ': ' . $message . '</warning>');
}
}
/**
* Abort the migration if the condition evalutes to TRUE.
*
* @param bool $condition
* @param string $message
*/
public function abortIf($condition, $message = '')
{
$message = (strlen($message)) ? $message : 'Unknown Reason';
if ($condition === true) {
throw new AbortMigrationException($message);
}
}
/**
* Skip this migration (but not the next ones) if condition evalutes to TRUE.
*
* @param bool $condition
* @param string $message
*/
public function skipIf($condition, $message = '')
{
$message = (strlen($message)) ? $message : 'Unknown Reason';
if ($condition === true) {
throw new SkipMigrationException($message);
}
}
public function preUp(Schema $schema)
{
}
public function postUp(Schema $schema)
{
}
public function preDown(Schema $schema)
{
}
public function postDown(Schema $schema)
{
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Migrations;
/**
* Class for Migrations specific exceptions
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Jonathan H. Wage <jonwage@gmail.com>
*/
class MigrationException extends \Exception
{
public static function migrationsNamespaceRequired()
{
return new self('Migrations namespace must be configured in order to use Doctrine migrations.', 2);
}
public static function migrationsDirectoryRequired()
{
return new self('Migrations directory must be configured in order to use Doctrine migrations.', 3);
}
public static function noMigrationsToExecute()
{
return new self('Could not find any migrations to execute.', 4);
}
public static function unknownMigrationVersion($version)
{
return new self(sprintf('Could not find migration version %s', $version), 5);
}
public static function alreadyAtVersion($version)
{
return new self(sprintf('Database is already at version %s', $version), 6);
}
public static function duplicateMigrationVersion($version, $class)
{
return new self(sprintf('Migration version %s already registered with class %s', $version, $class), 7);
}
public static function configurationFileAlreadyLoaded()
{
return new self(sprintf('Migrations configuration file already loaded'), 8);
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Migrations;
use Doctrine\DBAL\Migrations\Configuration\Configuration,
Doctrine\DBAL\Schema\Schema;
/**
* Class for running migrations to the current version or a manually specified version.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Jonathan H. Wage <jonwage@gmail.com>
*/
class Migration
{
/** The Doctrine\DBAL\Connection instance we are migrating */
private $_connection;
/** The OutputWriter object instance used for outputting information */
private $_outputWriter;
/**
* Construct a Migration instance
*
* @param Configuration $configuration A migration Configuration instance
*/
public function __construct(Configuration $configuration)
{
$this->_configuration = $configuration;
$this->_outputWriter = $configuration->getOutputWriter();
}
/**
* Get the array of versions and SQL queries that would be executed for
* each version but do not execute anything.
*
* @param string $to The version to migrate to.
* @return array $sql The array of SQL queries.
*/
public function getSql($to = null)
{
return $this->migrate($to, true);
}
/**
* Write a migration SQL file to the given path
*
* @param string $path The path to write the migration SQL file.
* @param string $to The version to migrate to.
* @return bool $written
*/
public function writeSqlFile($path, $to = null)
{
$sql = $this->getSql($to);
$from = $this->_configuration->getCurrentVersion();
if ($to === null) {
$to = $this->_configuration->getLatestVersion();
}
$string = sprintf("# Doctrine Migration File Generated on %s\n", date('Y-m-d H:m:s'));
$string .= sprintf("# Migrating from %s to %s\n", $from, $to);
foreach ($sql as $version => $queries) {
$string .= "\n# Version " . $version . "\n";
foreach ($queries as $query) {
$string .= $query . ";\n";
}
}
if (is_dir($path)) {
$path = realpath($path);
$path = $path . '/doctrine_migration_' . date('YmdHis') . '.sql';
}
$this->_outputWriter->write("\n".sprintf('Writing migration file to "<info>%s</info>"', $path));
return file_put_contents($path, $string);
}
/**
* Run a migration to the current version or the given target version.
*
* @param string $to The version to migrate to.
* @param string $dryRun Whether or not to make this a dry run and not execute anything.
* @return array $sql The array of migration sql statements
* @throws MigrationException
*/
public function migrate($to = null, $dryRun = false)
{
if ($to === null) {
$to = $this->_configuration->getLatestVersion();
}
$from = $this->_configuration->getCurrentVersion();
$from = (string) $from;
$to = (string) $to;
$migrations = $this->_configuration->getMigrations();
if ( ! isset($migrations[$to]) && $to > 0) {
throw MigrationException::unknownMigrationVersion($to);
}
if ($from === $to) {
throw MigrationException::alreadyAtVersion($to);
}
$direction = $from > $to ? 'down' : 'up';
$migrations = $this->_configuration->getMigrationsToExecute($direction, $to);
if ($dryRun === false) {
$this->_outputWriter->write(sprintf('Migrating <info>%s</info> to <comment>%s</comment> from <comment>%s</comment>', $direction, $to, $from));
} else {
$this->_outputWriter->write(sprintf('Executing dry run of migration <info>%s</info> to <comment>%s</comment> from <comment>%s</comment>', $direction, $to, $from));
}
if (empty($migrations)) {
throw MigrationException::noMigrationsToExecute();
}
$sql = array();
$time = 0;
foreach ($migrations as $version) {
$versionSql = $version->execute($direction, $dryRun);
$sql[$version->getVersion()] = $versionSql;
$time += $version->getTime();
}
$this->_outputWriter->write("\n <comment>------------------------</comment>\n");
$this->_outputWriter->write(sprintf(" <info>++</info> finished in %s", $time));
$this->_outputWriter->write(sprintf(" <info>++</info> %s migrations executed", count($migrations)));
$this->_outputWriter->write(sprintf(" <info>++</info> %s sql queries", count($sql, true) - count($sql)));
return $sql;
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Migrations\Configuration;
use Doctrine\DBAL\Connection,
Doctrine\DBAL\Migrations\MigrationException,
Doctrine\DBAL\Migrations\Version,
Doctrine\DBAL\Migrations\OutputWriter,
Doctrine\DBAL\Schema\Table,
Doctrine\DBAL\Schema\Column,
Doctrine\DBAL\Types\Type;
/**
* Default Migration Configurtion object used for configuring an instance of
* the Migration class. Set the connection, version table name, register migration
* classes/versions, etc.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Jonathan H. Wage <jonwage@gmail.com>
*/
class Configuration
{
/** Name of this set of migrations */
private $_name;
/** Flag for whether or not the migration table has been created */
private $_migrationTableCreated = false;
/** Connection instance to use for migrations */
private $_connection;
/** OutputWriter instance for writing output during migrations */
private $_outputWriter;
/** The migration table name to track versions in */
private $_migrationsTableName = 'doctrine_migration_versions';
/** The path to a directory where new migration classes will be written */
private $_migrationsDirectory;
/** Namespace the migration classes live in */
private $_migrationsNamespace;
/** Array of the registered migrations */
private $_migrations = array();
/**
* Construct a migration configuration object.
*
* @param Connection $connection A Connection instance
* @param OutputWriter $outputWriter A OutputWriter instance
*/
public function __construct(Connection $connection, OutputWriter $outputWriter = null)
{
$this->_connection = $connection;
if ($outputWriter === null) {
$outputWriter = new OutputWriter();
}
$this->_outputWriter = $outputWriter;
}
/**
* Validation that this instance has all the required properties configured
*
* @return void
* @throws MigrationException
*/
public function validate()
{
if ( ! $this->_migrationsNamespace) {
throw MigrationException::migrationsNamespaceRequired();
}
if ( ! $this->_migrationsDirectory) {
throw MigrationException::migrationsDirectoryRequired();
}
}
/**
* Set the name of this set of migrations
*
* @param string $name The name of this set of migrations
*/
public function setName($name)
{
$this->_name = $name;
}
/**
* Returns the name of this set of migrations
*
* @return string $name The name of this set of migrations
*/
public function getName()
{
return $this->_name;
}
/**
* Returns the OutputWriter instance
*
* @return OutputWriter $outputWriter The OutputWriter instance
*/
public function getOutputWriter()
{
return $this->_outputWriter;
}
/**
* Returns a timestamp version as a formatted date
*
* @param string $version
* @return string $formattedVersion The formatted version
*/
public function formatVersion($version)
{
return sprintf('%s-%s-%s %s:%s:%s',
substr($version, 0, 4),
substr($version, 4, 2),
substr($version, 6, 2),
substr($version, 8, 2),
substr($version, 10, 2),
substr($version, 12, 2)
);
}
/**
* Returns the Connection instance
*
* @return Connection $connection The Connection instance
*/
public function getConnection()
{
return $this->_connection;
}
/**
* Set the migration table name
*
* @param string $tableName The migration table name
*/
public function setMigrationsTableName($tableName)
{
$this->_migrationsTableName = $tableName;
}
/**
* Returns the migration table name
*
* @return string $migrationsTableName The migration table name
*/
public function getMigrationsTableName()
{
return $this->_migrationsTableName;
}
/**
* Set the new migrations directory where new migration classes are generated
*
* @param string $migrationsDirectory The new migrations directory
*/
public function setMigrationsDirectory($migrationsDirectory)
{
$this->_migrationsDirectory = $migrationsDirectory;
}
/**
* Returns the new migrations directory where new migration classes are generated
*
* @return string $migrationsDirectory The new migrations directory
*/
public function getMigrationsDirectory()
{
return $this->_migrationsDirectory;
}
/**
* Set the migrations namespace
*
* @param string $migrationsNamespace The migrations namespace
*/
public function setMigrationsNamespace($migrationsNamespace)
{
$this->_migrationsNamespace = $migrationsNamespace;
}
/**
* Returns the migrations namespace
*
* @return string $migrationsNamespace The migrations namespace
*/
public function getMigrationsNamespace()
{
return $this->_migrationsNamespace;
}
/**
* Register migrations from a given directory. Recursively finds all files
* with the pattern VersionYYYYMMDDHHMMSS.php as the filename and registers
* them as migrations.
*
* @param string $path The root directory to where some migration classes live.
* @return $migrations The array of migrations registered.
*/
public function registerMigrationsFromDirectory($path)
{
$path = realpath($path);
$path = rtrim($path, '/');
$files = glob($path . '/Version*.php');
$versions = array();
foreach ($files as $file) {
require_once($file);
$info = pathinfo($file);
$version = substr($info['filename'], 7);
$class = $this->_migrationsNamespace . '\\' . $info['filename'];
$versions[] = $this->registerMigration($version, $class);
}
return $versions;
}
/**
* Register a single migration version to be executed by a AbstractMigration
* class.
*
* @param string $version The version of the migration in the format YYYYMMDDHHMMSS.
* @param string $class The migration class to execute for the version.
*/
public function registerMigration($version, $class)
{
$version = (string) $version;
$class = (string) $class;
if (isset($this->_migrations[$version])) {
throw MigrationException::duplicateMigrationVersion($version, get_class($this->_migrations[$version]));
}
$version = new Version($this, $version, $class);
$this->_migrations[$version->getVersion()] = $version;
ksort($this->_migrations);
return $version;
}
/**
* Register an array of migrations. Each key of the array is the version and
* the value is the migration class name.
*
*
* @param array $migrations
* @return void
*/
public function registerMigrations(array $migrations)
{
$versions = array();
foreach ($migrations as $version => $class) {
$versions[] = $this->registerMigration($version, $class);
}
return $versions;
}
/**
* Get the array of registered migration versions.
*
* @return array $migrations
*/
public function getMigrations()
{
return $this->_migrations;
}
/**
* Returns the Version instance for a given version in the format YYYYMMDDHHMMSS.
*
* @param string $version The version string in the format YYYYMMDDHHMMSS.
* @return Version $version
* @throws MigrationException $exception Throws exception if migration version does not exist.
*/
public function getVersion($version)
{
if ( ! isset($this->_migrations[$version])) {
MigrationException::unknownMigrationVersion($version);
}
return $this->_migrations[$version];
}
/**
* Check if a version exists.
*
* @param string $version
* @return bool $exists
*/
public function hasVersion($version)
{
return isset($this->_migrations[$version]) ? true : false;
}
/**
* Check if a version has been migrated or not yet
*
* @param Version $version
* @return bool $migrated
*/
public function hasVersionMigrated(Version $version)
{
$this->createMigrationTable();
$version = $this->_connection->fetchColumn("SELECT version FROM " . $this->_migrationsTableName . " WHERE version = '" . $version->getVersion() . "'");
return $version !== false ? true : false;
}
/**
* Returns the current migrated version from the versions table.
*
* @return bool $currentVersion
*/
public function getCurrentVersion()
{
$this->createMigrationTable();
$result = $this->_connection->fetchColumn("SELECT version FROM " . $this->_migrationsTableName . " ORDER BY version DESC LIMIT 1");
return $result !== false ? (string) $result : '0';
}
/**
* Returns the total number of executed migration versions
*
* @return integer $count
*/
public function getNumberOfExecutedMigrations()
{
$this->createMigrationTable();
$result = $this->_connection->fetchColumn("SELECT COUNT(version) FROM " . $this->_migrationsTableName);
return $result !== false ? $result : 0;
}
/**
* Returns the total number of available migration versions
*
* @return integer $count
*/
public function getNumberOfAvailableMigrations()
{
return count($this->_migrations);
}
/**
* Returns the latest available migration version.
*
* @return string $version The version string in the format YYYYMMDDHHMMSS.
*/
public function getLatestVersion()
{
$versions = array_keys($this->_migrations);
$latest = end($versions);
return $latest !== false ? (string) $latest : '0';
}
/**
* Create the migration table to track migrations with.
*
* @return bool $created Whether or not the table was created.
*/
public function createMigrationTable()
{
$this->validate();
if ($this->_migrationTableCreated) {
return false;
}
$schema = $this->_connection->getSchemaManager()->createSchema();
if ( ! $schema->hasTable($this->_migrationsTableName)) {
$columns = array(
'version' => new Column('version', Type::getType('string'), array('length' => 14)),
);
$table = new Table($this->_migrationsTableName, $columns);
$table->setPrimaryKey(array('version'));
$this->_connection->getSchemaManager()->createTable($table);
$this->_migrationTableCreated = true;
return true;
}
return false;
}
/**
* Returns the array of migrations to executed based on the given direction
* and target version number.
*
* @param string $direction The direction we are migrating.
* @param string $to The version to migrate to.
* @return array $migrations The array of migrations we can execute.
*/
public function getMigrationsToExecute($direction, $to)
{
if ($direction === 'down') {
$allVersions = array_reverse(array_keys($this->_migrations));
$classes = array_reverse(array_values($this->_migrations));
$allVersions = array_combine($allVersions, $classes);
} else {
$allVersions = $this->_migrations;
}
$versions = array();
foreach ($allVersions as $version) {
if ($this->_shouldExecuteMigration($direction, $version, $to)) {
$versions[$version->getVersion()] = $version;
}
}
return $versions;
}
/**
* Check if we should execute a migration for a given direction and target
* migration version.
*
* @param string $direction The direction we are migrating.
* @param Version $version The Version instance to check.
* @param string $to The version we are migrating to.
* @return void
*/
private function _shouldExecuteMigration($direction, Version $version, $to)
{
if ($direction === 'down') {
if ( ! $this->hasVersionMigrated($version)) {
return false;
}
return $version->getVersion() > $to ? true : false;
} else if ($direction === 'up') {
if ($this->hasVersionMigrated($version)) {
return false;
}
return $version->getVersion() <= $to ? true : false;
}
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Migrations\Configuration;
/**
* Load migration configuration information from a XML configuration file.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Jonathan H. Wage <jonwage@gmail.com>
*/
class XmlConfiguration extends AbstractFileConfiguration
{
/**
* @inheritdoc
*/
protected function _load($file)
{
$xml = simplexml_load_file($file);
if (isset($xml->name)) {
$this->setName((string) $xml->name);
}
if (isset($xml->table['name'])) {
$this->setMigrationsTableName((string) $xml->table['name']);
}
if (isset($xml->{'migrations-namespace'})) {
$this->setMigrationsNamespace((string) $xml->{'migrations-namespace'});
}
if (isset($xml->{'migrations-directory'})) {
$migrationsDirectory = $this->_getDirectoryRelativeToFile($file, (string) $xml->{'migrations-directory'});
$this->setMigrationsDirectory($migrationsDirectory);
$this->registerMigrationsFromDirectory($migrationsDirectory);
}
if (isset($xml->migrations->migration)) {
foreach ($xml->migrations->migration as $migration) {
$this->registerMigration((string) $migration['version'], (string) $migration['class']);
}
}
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Migrations\Configuration;
use Symfony\Component\Yaml\Yaml;
/**
* Load migration configuration information from a YAML configuration file.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Jonathan H. Wage <jonwage@gmail.com>
*/
class YamlConfiguration extends AbstractFileConfiguration
{
/**
* @inheritdoc
*/
protected function _load($file)
{
$array = Yaml::load($file);
if (isset($array['name'])) {
$this->setName($array['name']);
}
if (isset($array['table_name'])) {
$this->setMigrationsTableName($array['table_name']);
}
if (isset($array['migrations_namespace'])) {
$this->setMigrationsNamespace($array['migrations_namespace']);
}
if (isset($array['migrations_directory'])) {
$migrationsDirectory = $this->_getDirectoryRelativeToFile($file, $array['migrations_directory']);
$this->setMigrationsDirectory($migrationsDirectory);
$this->registerMigrationsFromDirectory($migrationsDirectory);
}
if (isset($array['migrations']) && is_array($array['migrations'])) {
foreach ($array['migrations'] as $migration) {
$this->registerMigration($migration['version'], $migration['class']);
}
}
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Migrations\Configuration;
use Doctrine\DBAL\Migrations\MigrationsException;
/**
* Abstract Migration Configuration class for loading configuration information
* from a configuration file (xml or yml).
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Jonathan H. Wage <jonwage@gmail.com>
*/
abstract class AbstractFileConfiguration extends Configuration
{
/** The configuration file used to load configuration information */
private $_file;
/** Whether or not the configuration file has been loaded yet or not */
private $_loaded = false;
/**
* Load the information from the passed configuration file
*
* @param string $file The path to the configuration file
* @return void
* @throws MigrationException $exception Throws exception if configuration file was already loaded
*/
public function load($file)
{
if ($this->_loaded) {
throw MigrationsException::configurationFileAlreadyLoaded();
}
if (file_exists($path = getcwd() . '/' . $file)) {
$file = $path;
}
$this->_file = $file;
$this->_load($file);
$this->_loaded = true;
}
protected function _getDirectoryRelativeToFile($file, $input)
{
$path = realpath(dirname($file) . '/' . $input);
if ($path !== false) {
$directory = $path;
} else {
$directory = $input;
}
return $directory;
}
public function getFile()
{
return $this->_file;
}
/**
* Abstract method that each file configuration driver must implement to
* load the given configuration file whether it be xml, yaml, etc. or something
* else.
*
* @param string $file The path to a configuration file.
*/
abstract protected function _load($file);
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Migrations;
/**
* Simple class for outputting information from migrations.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Jonathan H. Wage <jonwage@gmail.com>
*/
class OutputWriter
{
private $_closure;
public function __construct(\Closure $closure = null)
{
if ($closure === null) {
$closure = function($message) {};
}
$this->_closure = $closure;
}
/**
* Write output using the configured closure.
*
* @param string $message The message to write.
*/
public function write($message)
{
$closure = $this->_closure;
$closure($message);
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Migrations;
use Doctrine\DBAL\Migrations\Configuration\Configuration,
Doctrine\DBAL\Schema\Schema;
/**
* Class which wraps a migration version and allows execution of the
* individual migration version up or down method.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Jonathan H. Wage <jonwage@gmail.com>
*/
class Version
{
const STATE_NONE = 0;
const STATE_PRE = 1;
const STATE_EXEC = 2;
const STATE_POST = 3;
/**
* The Migrations Configuration instance for this migration
*
* @var Configuration
*/
private $_configuration;
/**
* The OutputWriter object instance used for outputting information
*
* @var OutputWriter
*/
private $_outputWriter;
/**
* The version in timestamp format (YYYYMMDDHHMMSS)
*
* @param int
*/
private $_version;
/**
* @var AbstractSchemaManager
*/
private $_sm;
/**
* @var AbstractPlatform
*/
private $_platform;
/**
* The migration instance for this version
*
* @var AbstractMigration
*/
private $_migration;
/**
* @var Connection
*/
private $_connection;
/**
* @var string
*/
private $_class;
/** The array of collected SQL statements for this version */
private $_sql = array();
/** The time in seconds that this migration version took to execute */
private $_time;
/**
* @var int
*/
private $_state = self::STATE_NONE;
public function __construct(Configuration $configuration, $version, $class)
{
$this->_configuration = $configuration;
$this->_outputWriter = $configuration->getOutputWriter();
$this->_version = $version;
$this->_class = $class;
$this->_connection = $configuration->getConnection();
$this->_sm = $this->_connection->getSchemaManager();
$this->_platform = $this->_connection->getDatabasePlatform();
$this->_migration = new $class($this);
}
/**
* Returns the string version in the format YYYYMMDDHHMMSS
*
* @return string $version
*/
public function getVersion()
{
return $this->_version;
}
/**
* Returns the Migrations Configuration object instance
*
* @return Configuration $configuration
*/
public function getConfiguration()
{
return $this->_configuration;
}
/**
* Check if this version has been migrated or not.
*
* @param bool $bool
* @return mixed
*/
public function isMigrated()
{
return $this->_configuration->hasVersionMigrated($this);
}
public function markMigrated()
{
$this->_configuration->createMigrationTable();
$this->_connection->executeQuery("INSERT INTO " . $this->_configuration->getMigrationsTableName() . " (version) VALUES (?)", array($this->_version));
}
public function markNotMigrated()
{
$this->_configuration->createMigrationTable();
$this->_connection->executeQuery("DELETE FROM " . $this->_configuration->getMigrationsTableName() . " WHERE version = '$this->_version'");
}
/**
* Add some SQL queries to this versions migration
*
* @param mixed $sql
* @return void
*/
public function addSql($sql)
{
if (is_array($sql)) {
foreach ($sql as $query) {
$this->_sql[] = $query;
}
} else {
$this->_sql[] = $sql;
}
}
/**
* Write a migration SQL file to the given path
*
* @param string $path The path to write the migration SQL file.
* @param string $direction The direction to execute.
* @return bool $written
*/
public function writeSqlFile($path, $direction = 'up')
{
$queries = $this->execute($direction, true);
$string = sprintf("# Doctrine Migration File Generated on %s\n", date('Y-m-d H:m:s'));
$string .= "\n# Version " . $this->_version . "\n";
foreach ($queries as $query) {
$string .= $query . ";\n";
}
if (is_dir($path)) {
$path = realpath($path);
$path = $path . '/doctrine_migration_' . date('YmdHis') . '.sql';
}
$this->_outputWriter->write("\n".sprintf('Writing migration file to "<info>%s</info>"', $path));
return file_put_contents($path, $string);
}
/**
* Execute this migration version up or down and and return the SQL.
*
* @param string $direction The direction to execute the migration.
* @param string $dryRun Whether to not actually execute the migration SQL and just do a dry run.
* @return array $sql
* @throws Exception when migration fails
*/
public function execute($direction, $dryRun = false)
{
$this->_sql = array();
$this->_connection->beginTransaction();
try {
$start = microtime(true);
$this->_state = self::STATE_PRE;
$fromSchema = $this->_sm->createSchema();
$this->_migration->{'pre' . ucfirst($direction)}($fromSchema);
if ($direction === 'up') {
$this->_outputWriter->write("\n" . sprintf(' <info>++</info> migrating <comment>%s</comment>', $this->_version) . "\n");
} else {
$this->_outputWriter->write("\n" . sprintf(' <info>--</info> reverting <comment>%s</comment>', $this->_version) . "\n");
}
$this->_state = self::STATE_EXEC;
$toSchema = clone $fromSchema;
$this->_migration->$direction($toSchema);
$this->addSql($fromSchema->getMigrateToSql($toSchema, $this->_platform));
if ($dryRun === false) {
if ($this->_sql) {
$count = count($this->_sql);
foreach ($this->_sql as $query) {
$this->_outputWriter->write(' <comment>-></comment> ' . $query);
$this->_connection->executeQuery($query);
}
if ($direction === 'up') {
$this->markMigrated();
} else {
$this->markNotMigrated();
}
} else {
$this->_outputWriter->write(sprintf('<error>Migration %s was executed but did not result in any SQL statements.</error>', $this->_version));
}
} else {
foreach ($this->_sql as $query) {
$this->_outputWriter->write(' <comment>-></comment> ' . $query);
}
}
$this->_state = self::STATE_POST;
$this->_migration->{'post' . ucfirst($direction)}($toSchema);
$end = microtime(true);
$this->_time = round($end - $start, 2);
if ($direction === 'up') {
$this->_outputWriter->write(sprintf("\n <info>++</info> migrated (%ss)", $this->_time));
} else {
$this->_outputWriter->write(sprintf("\n <info>--</info> reverted (%ss)", $this->_time));
}
$this->_connection->commit();
return $this->_sql;
} catch(SkipMigrationException $e) {
$this->_connection->rollback();
// now mark it as migrated
if ($direction === 'up') {
$this->markMigrated();
} else {
$this->markNotMigrated();
}
$this->_outputWriter->write(sprintf("\n <info>SS</info> skipped (Reason: %s)", $e->getMessage()));
} catch (\Exception $e) {
$this->_outputWriter->write(sprintf(
'<error>Migration %s failed during %s. Error %s</error>',
$this->_version, $this->getExecutionState(), $e->getMessage()
));
$this->_connection->rollback();
$this->_state = self::STATE_NONE;
throw $e;
}
$this->_state = self::STATE_NONE;
}
public function getExecutionState()
{
switch($this->_state) {
case self::STATE_PRE:
return 'Pre-Checks';
case self::STATE_POST:
return 'Post-Checks';
case self::STATE_EXEC:
return 'Execution';
default:
return 'No State';
}
}
/**
* Returns the time this migration version took to execute
*
* @return integer $time The time this migration version took to execute
*/
public function getTime()
{
return $this->_time;
}
public function __toString()
{
return $this->_version;
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Migrations;
class MigrationsVersion
{
const VERSION = '2.0.0-DEV';
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Migrations\Tools\Console\Command;
use Symfony\Component\Console\Input\InputInterface,
Symfony\Component\Console\Output\OutputInterface,
Symfony\Component\Console\Input\InputArgument,
Symfony\Component\Console\Input\InputOption,
Doctrine\ORM\Tools\SchemaTool,
Doctrine\DBAL\Migrations\Configuration\Configuration;
/**
* Command for generate migration classes by comparing your current database schema
* to your mapping information.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Jonathan Wage <jonwage@gmail.com>
*/
class DiffCommand extends GenerateCommand
{
protected function configure()
{
parent::configure();
$this
->setName('migrations:diff')
->setDescription('Generate a migration by comparing your current database to your mapping information.')
->setHelp(<<<EOT
The <info>%command.name%</info> command generates a migration by comparing your current database to your mapping information:
<info>%command.full_name%</info>
You can optionally specify a <comment>--editor-cmd</comment> option to open the generated file in your favorite editor:
<info>%command.full_name% --editor-cmd=mate</info>
EOT
);
}
public function execute(InputInterface $input, OutputInterface $output)
{
$configuration = $this->_getMigrationConfiguration($input, $output);
$em = $this->getHelper('em')->getEntityManager();
$conn = $em->getConnection();
$platform = $conn->getDatabasePlatform();
$metadata = $em->getMetadataFactory()->getAllMetadata();
if (empty($metadata)) {
$output->writeln('No mapping information to process.', 'ERROR');
return;
}
$tool = new SchemaTool($em);
$fromSchema = $conn->getSchemaManager()->createSchema();
$toSchema = $tool->getSchemaFromMetadata($metadata);
$up = $this->_buildCodeFromSql($configuration, $fromSchema->getMigrateToSql($toSchema, $platform));
$down = $this->_buildCodeFromSql($configuration, $fromSchema->getMigrateFromSql($toSchema, $platform));
if ( ! $up && ! $down) {
$output->writeln('No changes detected in your mapping information.', 'ERROR');
return;
}
$version = date('YmdHis');
$path = $this->_generateMigration($configuration, $input, $version, $up, $down);
$output->writeln(sprintf('Generated new migration class to "<info>%s</info>" from schema differences.', $path));
}
private function _buildCodeFromSql(Configuration $configuration, array $sql)
{
$code = array();
foreach ($sql as $query) {
if (strpos($query, $configuration->getMigrationsTableName()) !== false) {
continue;
}
$code[] = "\$this->_addSql('" . $query . "');";
}
return implode("\n", $code);
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Migrations\Tools\Console\Command;
use Symfony\Component\Console\Command\Command,
Symfony\Component\Console\Input\InputInterface,
Symfony\Component\Console\Output\OutputInterface,
Symfony\Component\Console\Input\InputOption,
Doctrine\DBAL\Migrations\Migration,
Doctrine\DBAL\Migrations\MigrationException,
Doctrine\DBAL\Migrations\OutputWriter,
Doctrine\DBAL\Migrations\Configuration\Configuration,
Doctrine\DBAL\Migrations\Configuration\YamlConfiguration,
Doctrine\DBAL\Migrations\Configuration\XmlConfiguration;
/**
* CLI Command for adding and deleting migration versions from the version table.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Jonathan Wage <jonwage@gmail.com>
*/
abstract class AbstractCommand extends Command
{
protected $_configuration;
protected function configure()
{
$this->addOption('configuration', null, InputOption::PARAMETER_OPTIONAL, 'The path to a migrations configuration file.');
$this->addOption('db-configuration', null, InputOption::PARAMETER_OPTIONAL, 'The path to a database connection configuration file.');
}
protected function _outputHeader(Configuration $configuration, OutputInterface $output)
{
$name = $configuration->getName();
$name = $name ? $name : 'Doctrine Database Migrations';
$name = str_repeat(' ', 20) . $name . str_repeat(' ', 20);
$output->writeln('<question>' . str_repeat(' ', strlen($name)) . '</question>');
$output->writeln('<question>' . $name . '</question>');
$output->writeln('<question>' . str_repeat(' ', strlen($name)) . '</question>');
$output->writeln('');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return Configuration
*/
protected function _getMigrationConfiguration(InputInterface $input, OutputInterface $output)
{
if ( ! $this->_configuration) {
$outputWriter = new OutputWriter(function($message) use ($output) {
return $output->writeln($message);
});
if ($this->application->getHelperSet()->has('db')) {
$conn = $this->getHelper('db')->getConnection();
} else if($input->getOption('db-configuration')) {
if (!file_exists($input->getOption('db-configuration'))) {
throw new \InvalidArgumentException("The specified connection file is a valid file.");
}
$params = include($input->getOption('db-configuration'));
if (!is_array($params)) {
throw new \InvalidArgumentException('The connection file has to return an array with database configuration parameters.');
}
$conn = \Doctrine\DBAL\DriverManager::getConnection($params);
} else if (file_exists('migrations-db.php')) {
$params = include("migrations-db.php");
if (!is_array($params)) {
throw new \InvalidArgumentException('The connection file has to return an array with database configuration parameters.');
}
$conn = \Doctrine\DBAL\DriverManager::getConnection($params);
} else {
throw new \InvalidArgumentException('You have to specify a --db-configuration file or pass a Database Connection as a dependency to the Migrations.');
}
if ($input->getOption('configuration')) {
$info = pathinfo($input->getOption('configuration'));
$class = $info['extension'] === 'xml' ? 'Doctrine\DBAL\Migrations\Configuration\XmlConfiguration' : 'Doctrine\DBAL\Migrations\Configuration\YamlConfiguration';
$configuration = new $class($conn, $outputWriter);
$configuration->load($input->getOption('configuration'));
} else if (file_exists('migrations.xml')) {
$configuration = new XmlConfiguration($conn, $outputWriter);
$configuration->load('migrations.xml');
} else if (file_exists('migrations.yml')) {
$configuration = new YamlConfiguration($conn, $outputWriter);
$configuration->load('migrations.yml');
} else {
$configuration = new Configuration($conn, $outputWriter);
}
$this->_configuration = $configuration;
}
return $this->_configuration;
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Migrations\Tools\Console\Command;
use Symfony\Component\Console\Input\InputInterface,
Symfony\Component\Console\Output\OutputInterface,
Symfony\Component\Console\Input\InputArgument,
Symfony\Component\Console\Input\InputOption,
Doctrine\DBAL\Migrations\MigrationException,
Doctrine\DBAL\Migrations\Configuration\Configuration;
/**
* Command for generating new blank migration classes
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Jonathan Wage <jonwage@gmail.com>
*/
class GenerateCommand extends AbstractCommand
{
private static $_template =
'<?php
namespace <namespace>;
use Doctrine\DBAL\Migrations\AbstractMigration,
Doctrine\DBAL\Schema\Schema;
class Version<version> extends AbstractMigration
{
public function up(Schema $schema)
{
<up>
}
public function down(Schema $schema)
{
<down>
}
}';
protected function configure()
{
$this
->setName('migrations:generate')
->setDescription('Generate a blank migration class.')
->addOption('editor-cmd', null, InputOption::PARAMETER_OPTIONAL, 'Open file with this command upon creation.')
->setHelp(<<<EOT
The <info>%command.name%</info> command generates a blank migration class:
<info>%command.full_name%</info>
You can optionally specify a <comment>--editor-cmd</comment> option to open the generated file in your favorite editor:
<info>%command.full_name% --editor-cmd=mate</info>
EOT
);
parent::configure();
}
public function execute(InputInterface $input, OutputInterface $output)
{
$configuration = $this->_getMigrationConfiguration($input, $output);
$version = date('YmdHis');
$path = $this->_generateMigration($configuration, $input, $version);
$output->writeln(sprintf('Generated new migration class to "<info>%s</info>"', $path));
}
protected function _generateMigration(Configuration $configuration, InputInterface $input, $version, $up = null, $down = null)
{
$placeHolders = array(
'<namespace>',
'<version>',
'<up>',
'<down>'
);
$replacements = array(
$configuration->getMigrationsNamespace(),
$version,
$up ? " " . implode("\n ", explode("\n", $up)) : null,
$down ? " " . implode("\n ", explode("\n", $down)) : null
);
$code = str_replace($placeHolders, $replacements, self::$_template);
$dir = $configuration->getMigrationsDirectory();
$dir = $dir ? $dir : getcwd();
$dir = rtrim($dir, '/');
$path = $dir . '/Version' . $version . '.php';
file_put_contents($path, $code);
if ($editorCmd = $input->getOption('editor-cmd'))
{
shell_exec($editorCmd . ' ' . escapeshellarg($path));
}
return $path;
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Migrations\Tools\Console\Command;
use Symfony\Component\Console\Input\InputInterface,
Symfony\Component\Console\Output\OutputInterface,
Symfony\Component\Console\Input\InputArgument,
Symfony\Component\Console\Input\InputOption,
Doctrine\DBAL\Migrations\Migration,
Doctrine\DBAL\Migrations\MigrationException,
Doctrine\DBAL\Migrations\Configuration\Configuration,
Doctrine\DBAL\Migrations\Configuration\YamlConfiguration,
Doctrine\DBAL\Migrations\Configuration\XmlConfiguration;
/**
* Command for manually adding and deleting migration versions from the version table.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Jonathan Wage <jonwage@gmail.com>
*/
class VersionCommand extends AbstractCommand
{
protected function configure()
{
$this
->setName('migrations:version')
->setDescription('Manually add and delete migration versions from the version table.')
->addArgument('version', InputArgument::REQUIRED, 'The version to add or delete.', null)
->addOption('add', null, InputOption::PARAMETER_NONE, 'Add the specified version.')
->addOption('delete', null, InputOption::PARAMETER_NONE, 'Delete the specified version.')
->setHelp(<<<EOT
The <info>%command.name%</info> command allows you to manually add and delete migration versions from the version table:
<info>%command.full_name% YYYYMMDDHHMMSS --add</info>
If you want to delete a version you can use the <comment>--delete</comment> option:
<info>%command.full_name% YYYYMMDDHHMMSS --delete</info>
EOT
);
parent::configure();
}
public function execute(InputInterface $input, OutputInterface $output)
{
$configuration = $this->_getMigrationConfiguration($input, $output);
$migration = new Migration($configuration);
if ($input->getOption('add') === false && $input->getOption('delete') === false) {
throw new \InvalidArgumentException('You must specify whether you want to --add or --delete the specified version.');
}
$version = $input->getArgument('version');
$markMigrated = $input->getOption('add') ? true : false;
if ( ! $configuration->hasVersion($version)) {
throw MigrationException::unknownMigrationVersion($version);
}
$version = $configuration->getVersion($version);
if ($markMigrated && $configuration->hasVersionMigrated($version)) {
throw new \InvalidArgumentException(sprintf('The version "%s" already exists in the version table.', $version));
}
if ( ! $markMigrated && ! $configuration->hasVersionMigrated($version)) {
throw new \InvalidArgumentException(sprintf('The version "%s" does not exists in the version table.', $version));
}
if ($markMigrated) {
$version->markMigrated();
} else {
$version->markNotMigrated();
}
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Migrations\Tools\Console\Command;
use Symfony\Component\Console\Input\InputInterface,
Symfony\Component\Console\Output\OutputInterface,
Symfony\Component\Console\Input\InputArgument,
Symfony\Component\Console\Input\InputOption,
Doctrine\DBAL\Migrations\Migration,
Doctrine\DBAL\Migrations\Configuration\Configuration,
Doctrine\DBAL\Migrations\Configuration\YamlConfiguration,
Doctrine\DBAL\Migrations\Configuration\XmlConfiguration;
/**
* Command for executing single migrations up or down manually.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Jonathan Wage <jonwage@gmail.com>
*/
class ExecuteCommand extends AbstractCommand
{
protected function configure()
{
$this
->setName('migrations:execute')
->setDescription('Execute a single migration version up or down manually.')
->addArgument('version', InputArgument::REQUIRED, 'The version to execute.', null)
->addOption('write-sql', null, InputOption::PARAMETER_NONE, 'The path to output the migration SQL file instead of executing it.')
->addOption('dry-run', null, InputOption::PARAMETER_NONE, 'Execute the migration as a dry run.')
->addOption('up', null, InputOption::PARAMETER_NONE, 'Execute the migration down.')
->addOption('down', null, InputOption::PARAMETER_NONE, 'Execute the migration down.')
->setHelp(<<<EOT
The <info>%command.name%</info> command executes a single migration version up or down manually:
<info>%command.full_name% YYYYMMDDHHMMSS</info>
If no <comment>--up</comment> or <comment>--down</comment> option is specified it defaults to up:
<info>%command.full_name% YYYYMMDDHHMMSS --down</info>
You can also execute the migration as a <comment>--dry-run</comment>:
<info>%command.full_name% YYYYMMDDHHMMSS --dry-run</info>
Or you can output the would be executed SQL statements to a file with <comment>--write-sql</comment>:
<info>%command.full_name% YYYYMMDDHHMMSS --write-sql</info>
EOT
);
parent::configure();
}
public function execute(InputInterface $input, OutputInterface $output)
{
$version = $input->getArgument('version');
$direction = $input->getOption('down') ? 'down' : 'up';
$configuration = $this->_getMigrationConfiguration($input, $output);
$version = $configuration->getVersion($version);
if ($path = $input->getOption('write-sql')) {
$path = is_bool($path) ? getcwd() : $path;
$version->writeSqlFile($path, $direction);
} else {
$confirmation = $this->getHelper('dialog')->askConfirmation($output, '<question>WARNING! You are about to execute a database migration that could result in schema changes and data lost. Are you sure you wish to continue? (y/n)</question>', 'y');
if ($confirmation === true) {
$version->execute($direction, $input->getOption('dry-run') ? true : false);
} else {
$output->writeln('<error>Migration cancelled!</error>');
}
}
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Migrations\Tools\Console\Command;
use Symfony\Component\Console\Input\InputInterface,
Symfony\Component\Console\Output\OutputInterface,
Symfony\Component\Console\Input\InputArgument,
Symfony\Component\Console\Input\InputOption,
Doctrine\DBAL\Migrations\Migration,
Doctrine\DBAL\Migrations\MigrationException,
Doctrine\DBAL\Migrations\Configuration\Configuration,
Doctrine\DBAL\Migrations\Configuration\YamlConfiguration,
Doctrine\DBAL\Migrations\Configuration\XmlConfiguration;
/**
* Command to view the status of a set of migrations.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Jonathan Wage <jonwage@gmail.com>
*/
class StatusCommand extends AbstractCommand
{
protected function configure()
{
$this
->setName('migrations:status')
->setDescription('View the status of a set of migrations.')
->addOption('show-versions', null, InputOption::PARAMETER_NONE, 'This will display a list of all available migrations and their status')
->setHelp(<<<EOT
The <info>%command.name%</info> command outputs the status of a set of migrations:
<info>%command.full_name%</info>
You can output a list of all available migrations and their status with <comment>--show-versions</comment>:
<info>%command.full_name% --show-versions</info>
EOT
);
parent::configure();
}
public function execute(InputInterface $input, OutputInterface $output)
{
$configuration = $this->_getMigrationConfiguration($input, $output);
$currentVersion = $configuration->getCurrentVersion();
if ($currentVersion) {
$currentVersionFormatted = $configuration->formatVersion($currentVersion) . ' (<comment>'.$currentVersion.'</comment>)';
} else {
$currentVersionFormatted = 0;
}
$latestVersion = $configuration->getLatestVersion();
if ($latestVersion) {
$latestVersionFormatted = $configuration->formatVersion($latestVersion) . ' (<comment>'.$latestVersion.'</comment>)';
} else {
$latestVersionFormatted = 0;
}
$executedMigrations = $configuration->getNumberOfExecutedMigrations();
$availableMigrations = $configuration->getNumberOfAvailableMigrations();
$newMigrations = $availableMigrations - $executedMigrations;
$output->writeln("\n <info>==</info> Configuration\n");
$info = array(
'Name' => $configuration->getName() ? $configuration->getName() : 'Doctrine Database Migrations',
'Database Driver' => $configuration->getConnection()->getDriver()->getName(),
'Database Name' => $configuration->getConnection()->getDatabase(),
'Configuration Source' => $configuration instanceof \Doctrine\DBAL\Migrations\Configuration\AbstractFileConfiguration ? $configuration->getFile() : 'manually configured',
'Version Table Name' => $configuration->getMigrationsTableName(),
'Migrations Namespace' => $configuration->getMigrationsNamespace(),
'Migrations Directory' => $configuration->getMigrationsDirectory(),
'Current Version' => $currentVersionFormatted,
'Latest Version' => $latestVersionFormatted,
'Executed Migrations' => $executedMigrations,
'Available Migrations' => $availableMigrations,
'New Migrations' => $newMigrations > 0 ? '<question>' . $newMigrations . '</question>' : $newMigrations
);
foreach ($info as $name => $value) {
$output->writeln(' <comment>>></comment> ' . $name . ': ' . str_repeat(' ', 50 - strlen($name)) . $value);
}
$showVersions = $input->getOption('show-versions') ? true : false;
if ($showVersions === true) {
if ($migrations = $configuration->getMigrations()) {
$output->writeln("\n <info>==</info> Migration Versions\n");
foreach ($migrations as $version) {
$isMigrated = $version->isMigrated();
$status = $isMigrated ? '<info>migrated</info>' : '<error>not migrated</error>';
$output->writeln(' <comment>>></comment> ' . $configuration->formatVersion($version->getVersion()) . ' (<comment>' . $version->getVersion() . '</comment>)' . str_repeat(' ', 30 - strlen($name)) . $status);
}
}
}
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Migrations\Tools\Console\Command;
use Symfony\Component\Console\Input\InputInterface,
Symfony\Component\Console\Output\OutputInterface,
Symfony\Component\Console\Input\InputArgument,
Symfony\Component\Console\Input\InputOption,
Doctrine\DBAL\Migrations\Migration,
Doctrine\DBAL\Migrations\Configuration\Configuration,
Doctrine\DBAL\Migrations\Configuration\YamlConfiguration,
Doctrine\DBAL\Migrations\Configuration\XmlConfiguration;
/**
* Command for executing a migration to a specified version or the latest available version.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Jonathan Wage <jonwage@gmail.com>
*/
class MigrateCommand extends AbstractCommand
{
protected function configure()
{
$this
->setName('migrations:migrate')
->setDescription('Execute a migration to a specified version or the latest available version.')
->addArgument('version', InputArgument::OPTIONAL, 'The version to migrate to.', null)
->addOption('write-sql', null, InputOption::PARAMETER_NONE, 'The path to output the migration SQL file instead of executing it.')
->addOption('dry-run', null, InputOption::PARAMETER_NONE, 'Execute the migration as a dry run.')
->setHelp(<<<EOT
The <info>%command.name%</info> command executes a migration to a specified version or the latest available version:
<info>%command.full_name%</info>
You can optionally manually specify the version you wish to migrate to:
<info>%command.full_name% YYYYMMDDHHMMSS</info>
You can also execute the migration as a <comment>--dry-run</comment>:
<info>%command.full_name% YYYYMMDDHHMMSS --dry-run</info>
Or you can output the would be executed SQL statements to a file with <comment>--write-sql</comment>:
<info>%command.full_name% YYYYMMDDHHMMSS --write-sql</info>
You can also execute the migration without a warning message wich you need to interact with:
<info>%command.full_name% --no-interaction</info>
EOT
);
parent::configure();
}
public function execute(InputInterface $input, OutputInterface $output)
{
$version = $input->getArgument('version');
$configuration = $this->_getMigrationConfiguration($input, $output);
$migration = new Migration($configuration);
$this->_outputHeader($configuration, $output);
if ($path = $input->getOption('write-sql')) {
$path = is_bool($path) ? getcwd() : $path;
$migration->writeSqlFile($path, $version);
} else {
$dryRun = $input->getOption('dry-run') ? true : false;
if ($dryRun === true) {
$migration->migrate($version, true);
} else {
$noInteraction = $input->getOption('no-interaction') ? true : false;
if ($noInteraction === true) {
$migration->migrate($version, $dryRun);
} else {
$confirmation = $this->getHelper('dialog')->askConfirmation($output, '<question>WARNING! You are about to execute a database migration that could result in schema changes and data lost. Are you sure you wish to continue? (y/n)</question>', 'y');
if ($confirmation === true) {
$migration->migrate($version, $dryRun);
} else {
$output->writeln('<error>Migration cancelled!</error>');
}
}
}
}
}
}
<?php
namespace Doctrine\DBAL;
class DBALException extends \Exception
{
public static function notSupported($method)
{
return new self("Operation '$method' is not supported by platform.");
}
public static function invalidPlatformSpecified()
{
return new self(
"Invalid 'platform' option specified, need to give an instance of ".
"\Doctrine\DBAL\Platforms\AbstractPlatform.");
}
public static function invalidPdoInstance()
{
return new self(
"The 'pdo' option was used in DriverManager::getConnection() but no ".
"instance of PDO was given."
);
}
public static function driverRequired()
{
return new self("The options 'driver' or 'driverClass' are mandatory if no PDO ".
"instance is given to DriverManager::getConnection().");
}
public static function unknownDriver($unknownDriverName, array $knownDrivers)
{
return new self("The given 'driver' ".$unknownDriverName." is unknown, ".
"Doctrine currently supports only the following drivers: ".implode(", ", $knownDrivers));
}
public static function invalidWrapperClass($wrapperClass)
{
return new self("The given 'wrapperClass' ".$wrapperClass." has to be a ".
"subtype of \Doctrine\DBAL\Connection.");
}
public static function invalidDriverClass($driverClass)
{
return new self("The given 'driverClass' ".$driverClass." has to implement the ".
"\Doctrine\DBAL\Driver interface.");
}
/**
* @param string $tableName
* @return DBALException
*/
public static function invalidTableName($tableName)
{
return new self("Invalid table name specified: ".$tableName);
}
/**
* @param string $tableName
* @return DBALException
*/
public static function noColumnsSpecifiedForTable($tableName)
{
return new self("No columns specified for table ".$tableName);
}
public static function limitOffsetInvalid()
{
return new self("Invalid Offset in Limit Query, it has to be larger or equal to 0.");
}
public static function typeExists($name)
{
return new self('Type '.$name.' already exists.');
}
public static function unknownColumnType($name)
{
return new self('Unknown column type '.$name.' requested.');
}
public static function typeNotFound($name)
{
return new self('Type to be overwritten '.$name.' does not exist.');
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\PDOOracle;
use Doctrine\DBAL\Platforms;
class Driver implements \Doctrine\DBAL\Driver
{
public function connect(array $params, $username = null, $password = null, array $driverOptions = array())
{
return new \Doctrine\DBAL\Driver\PDOConnection(
$this->_constructPdoDsn($params),
$username,
$password,
$driverOptions
);
}
/**
* Constructs the Oracle PDO DSN.
*
* @return string The DSN.
*/
private function _constructPdoDsn(array $params)
{
$dsn = 'oci:';
if (isset($params['host'])) {
$dsn .= 'dbname=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)' .
'(HOST=' . $params['host'] . ')';
if (isset($params['port'])) {
$dsn .= '(PORT=' . $params['port'] . ')';
} else {
$dsn .= '(PORT=1521)';
}
$dsn .= '))(CONNECT_DATA=(SID=' . $params['dbname'] . ')))';
} else {
$dsn .= 'dbname=' . $params['dbname'];
}
if (isset($params['charset'])) {
$dsn .= ';charset=' . $params['charset'];
}
return $dsn;
}
public function getDatabasePlatform()
{
return new \Doctrine\DBAL\Platforms\OraclePlatform();
}
public function getSchemaManager(\Doctrine\DBAL\Connection $conn)
{
return new \Doctrine\DBAL\Schema\OracleSchemaManager($conn);
}
public function getName()
{
return 'pdo_oracle';
}
public function getDatabase(\Doctrine\DBAL\Connection $conn)
{
$params = $conn->getParams();
return $params['user'];
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\IBMDB2;
class DB2Connection implements \Doctrine\DBAL\Driver\Connection
{
private $_conn = null;
public function __construct(array $params, $username, $password, $driverOptions = array())
{
$isPersistant = (isset($params['persistent']) && $params['persistent'] == true);
if ($isPersistant) {
$this->_conn = db2_pconnect($params['dbname'], $username, $password, $driverOptions);
} else {
$this->_conn = db2_connect($params['dbname'], $username, $password, $driverOptions);
}
if (!$this->_conn) {
throw new DB2Exception(db2_conn_errormsg());
}
}
function prepare($sql)
{
$stmt = @db2_prepare($this->_conn, $sql);
if (!$stmt) {
throw new DB2Exception(db2_stmt_errormsg());
}
return new DB2Statement($stmt);
}
function query()
{
$args = func_get_args();
$sql = $args[0];
$stmt = $this->prepare($sql);
$stmt->execute();
return $stmt;
}
function quote($input, $type=\PDO::PARAM_STR)
{
$input = db2_escape_string($input);
if ($type == \PDO::PARAM_INT ) {
return $input;
} else {
return "'".$input."'";
}
}
function exec($statement)
{
$stmt = $this->prepare($statement);
$stmt->execute();
return $stmt->rowCount();
}
function lastInsertId($name = null)
{
return db2_last_insert_id($this->_conn);
}
function beginTransaction()
{
db2_autocommit($this->_conn, DB2_AUTOCOMMIT_OFF);
}
function commit()
{
if (!db2_commit($this->_conn)) {
throw new DB2Exception(db2_conn_errormsg($this->_conn));
}
db2_autocommit($this->_conn, DB2_AUTOCOMMIT_ON);
}
function rollBack()
{
if (!db2_rollback($this->_conn)) {
throw new DB2Exception(db2_conn_errormsg($this->_conn));
}
db2_autocommit($this->_conn, DB2_AUTOCOMMIT_ON);
}
function errorCode()
{
return db2_conn_error($this->_conn);
}
function errorInfo()
{
return array(
0 => db2_conn_errormsg($this->_conn),
1 => $this->errorCode(),
);
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\IBMDB2;
class DB2Statement implements \Doctrine\DBAL\Driver\Statement
{
private $_stmt = null;
private $_bindParam = array();
/**
* DB2_BINARY, DB2_CHAR, DB2_DOUBLE, or DB2_LONG
* @var <type>
*/
static private $_typeMap = array(
\PDO::PARAM_INT => DB2_LONG,
\PDO::PARAM_STR => DB2_CHAR,
);
public function __construct($stmt)
{
$this->_stmt = $stmt;
}
/**
* Binds a value to a corresponding named or positional
* placeholder in the SQL statement that was used to prepare the statement.
*
* @param mixed $param Parameter identifier. For a prepared statement using named placeholders,
* this will be a parameter name of the form :name. For a prepared statement
* using question mark placeholders, this will be the 1-indexed position of the parameter
*
* @param mixed $value The value to bind to the parameter.
* @param integer $type Explicit data type for the parameter using the PDO::PARAM_* constants.
*
* @return boolean Returns TRUE on success or FALSE on failure.
*/
function bindValue($param, $value, $type = null)
{
return $this->bindParam($param, $value, $type);
}
/**
* Binds a PHP variable to a corresponding named or question mark placeholder in the
* SQL statement that was use to prepare the statement. Unlike PDOStatement->bindValue(),
* the variable is bound as a reference and will only be evaluated at the time
* that PDOStatement->execute() is called.
*
* Most parameters are input parameters, that is, parameters that are
* used in a read-only fashion to build up the query. Some drivers support the invocation
* of stored procedures that return data as output parameters, and some also as input/output
* parameters that both send in data and are updated to receive it.
*
* @param mixed $param Parameter identifier. For a prepared statement using named placeholders,
* this will be a parameter name of the form :name. For a prepared statement
* using question mark placeholders, this will be the 1-indexed position of the parameter
*
* @param mixed $variable Name of the PHP variable to bind to the SQL statement parameter.
*
* @param integer $type Explicit data type for the parameter using the PDO::PARAM_* constants. To return
* an INOUT parameter from a stored procedure, use the bitwise OR operator to set the
* PDO::PARAM_INPUT_OUTPUT bits for the data_type parameter.
* @return boolean Returns TRUE on success or FALSE on failure.
*/
function bindParam($column, &$variable, $type = null)
{
$this->_bindParam[$column] =& $variable;
if ($type && isset(self::$_typeMap[$type])) {
$type = self::$_typeMap[$type];
} else {
$type = DB2_CHAR;
}
if (!db2_bind_param($this->_stmt, $column, "variable", DB2_PARAM_IN, $type)) {
throw new DB2Exception(db2_stmt_errormsg());
}
return true;
}
/**
* Closes the cursor, enabling the statement to be executed again.
*
* @return boolean Returns TRUE on success or FALSE on failure.
*/
function closeCursor()
{
if (!$this->_stmt) {
return false;
}
$this->_bindParam = array();
db2_free_result($this->_stmt);
$ret = db2_free_stmt($this->_stmt);
$this->_stmt = false;
return $ret;
}
/**
* columnCount
* Returns the number of columns in the result set
*
* @return integer Returns the number of columns in the result set represented
* by the PDOStatement object. If there is no result set,
* this method should return 0.
*/
function columnCount()
{
if (!$this->_stmt) {
return false;
}
return db2_num_fields($this->_stmt);
}
/**
* errorCode
* Fetch the SQLSTATE associated with the last operation on the statement handle
*
* @see Doctrine_Adapter_Interface::errorCode()
* @return string error code string
*/
function errorCode()
{
return db2_stmt_error();
}
/**
* errorInfo
* Fetch extended error information associated with the last operation on the statement handle
*
* @see Doctrine_Adapter_Interface::errorInfo()
* @return array error info array
*/
function errorInfo()
{
return array(
0 => db2_stmt_errormsg(),
1 => db2_stmt_error(),
);
}
/**
* Executes a prepared statement
*
* If the prepared statement included parameter markers, you must either:
* call PDOStatement->bindParam() to bind PHP variables to the parameter markers:
* bound variables pass their value as input and receive the output value,
* if any, of their associated parameter markers or pass an array of input-only
* parameter values
*
*
* @param array $params An array of values with as many elements as there are
* bound parameters in the SQL statement being executed.
* @return boolean Returns TRUE on success or FALSE on failure.
*/
function execute($params = null)
{
if (!$this->_stmt) {
return false;
}
/*$retval = true;
if ($params !== null) {
$retval = @db2_execute($this->_stmt, $params);
} else {
$retval = @db2_execute($this->_stmt);
}*/
if ($params === null) {
ksort($this->_bindParam);
$params = array_values($this->_bindParam);
}
$retval = @db2_execute($this->_stmt, $params);
if ($retval === false) {
throw new DB2Exception(db2_stmt_errormsg());
}
return $retval;
}
/**
* fetch
*
* @see Query::HYDRATE_* constants
* @param integer $fetchStyle Controls how the next row will be returned to the caller.
* This value must be one of the Query::HYDRATE_* constants,
* defaulting to Query::HYDRATE_BOTH
*
* @param integer $cursorOrientation For a PDOStatement object representing a scrollable cursor,
* this value determines which row will be returned to the caller.
* This value must be one of the Query::HYDRATE_ORI_* constants, defaulting to
* Query::HYDRATE_ORI_NEXT. To request a scrollable cursor for your
* PDOStatement object,
* you must set the PDO::ATTR_CURSOR attribute to Doctrine::CURSOR_SCROLL when you
* prepare the SQL statement with Doctrine_Adapter_Interface->prepare().
*
* @param integer $cursorOffset For a PDOStatement object representing a scrollable cursor for which the
* $cursorOrientation parameter is set to Query::HYDRATE_ORI_ABS, this value specifies
* the absolute number of the row in the result set that shall be fetched.
*
* For a PDOStatement object representing a scrollable cursor for
* which the $cursorOrientation parameter is set to Query::HYDRATE_ORI_REL, this value
* specifies the row to fetch relative to the cursor position before
* PDOStatement->fetch() was called.
*
* @return mixed
*/
function fetch($fetchStyle = \PDO::FETCH_BOTH)
{
switch ($fetchStyle) {
case \PDO::FETCH_BOTH:
return db2_fetch_both($this->_stmt);
case \PDO::FETCH_ASSOC:
return db2_fetch_assoc($this->_stmt);
case \PDO::FETCH_NUM:
return db2_fetch_array($this->_stmt);
default:
throw new DB2Exception("Given Fetch-Style " . $fetchStyle . " is not supported.");
}
}
/**
* Returns an array containing all of the result set rows
*
* @param integer $fetchStyle Controls how the next row will be returned to the caller.
* This value must be one of the Query::HYDRATE_* constants,
* defaulting to Query::HYDRATE_BOTH
*
* @param integer $columnIndex Returns the indicated 0-indexed column when the value of $fetchStyle is
* Query::HYDRATE_COLUMN. Defaults to 0.
*
* @return array
*/
function fetchAll($fetchStyle = \PDO::FETCH_BOTH)
{
$rows = array();
while ($row = $this->fetch($fetchStyle)) {
$rows[] = $row;
}
return $rows;
}
/**
* fetchColumn
* Returns a single column from the next row of a
* result set or FALSE if there are no more rows.
*
* @param integer $columnIndex 0-indexed number of the column you wish to retrieve from the row. If no
* value is supplied, PDOStatement->fetchColumn()
* fetches the first column.
*
* @return string returns a single column in the next row of a result set.
*/
function fetchColumn($columnIndex = 0)
{
$row = $this->fetch(\PDO::FETCH_NUM);
if ($row && isset($row[$columnIndex])) {
return $row[$columnIndex];
}
return false;
}
/**
* rowCount
* rowCount() returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement
* executed by the corresponding object.
*
* If the last SQL statement executed by the associated Statement object was a SELECT statement,
* some databases may return the number of rows returned by that statement. However,
* this behaviour is not guaranteed for all databases and should not be
* relied on for portable applications.
*
* @return integer Returns the number of rows.
*/
function rowCount()
{
return (@db2_num_rows($this->_stmt))?:0;
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\IBMDB2;
class DB2Exception extends \Exception
{
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\IBMDB2;
use Doctrine\DBAL\Driver,
Doctrine\DBAL\Connection;
/**
* IBM DB2 Driver
*
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class DB2Driver implements Driver
{
/**
* Attempts to create a connection with the database.
*
* @param array $params All connection parameters passed by the user.
* @param string $username The username to use when connecting.
* @param string $password The password to use when connecting.
* @param array $driverOptions The driver options to use when connecting.
* @return Doctrine\DBAL\Driver\Connection The database connection.
*/
public function connect(array $params, $username = null, $password = null, array $driverOptions = array())
{
if ( !isset($params['schema']) ) {
}
if ($params['host'] !== 'localhost' && $params['host'] != '127.0.0.1') {
// if the host isn't localhost, use extended connection params
$params['dbname'] = 'DRIVER={IBM DB2 ODBC DRIVER}' .
';DATABASE=' . $params['dbname'] .
';HOSTNAME=' . $params['host'] .
';PORT=' . $params['port'] .
';PROTOCOL=' . $params['protocol'] .
';UID=' . $username .
';PWD=' . $password .';';
$username = null;
$password = null;
}
return new DB2Connection($params, $username, $password, $driverOptions);
}
/**
* Gets the DatabasePlatform instance that provides all the metadata about
* the platform this driver connects to.
*
* @return Doctrine\DBAL\Platforms\AbstractPlatform The database platform.
*/
public function getDatabasePlatform()
{
return new \Doctrine\DBAL\Platforms\DB2Platform;
}
/**
* Gets the SchemaManager that can be used to inspect and change the underlying
* database schema of the platform this driver connects to.
*
* @param Doctrine\DBAL\Connection $conn
* @return Doctrine\DBAL\SchemaManager
*/
public function getSchemaManager(Connection $conn)
{
return new \Doctrine\DBAL\Schema\DB2SchemaManager($conn);
}
/**
* Gets the name of the driver.
*
* @return string The name of the driver.
*/
public function getName()
{
return 'ibm_db2';
}
/**
* Get the name of the database connected to for this driver.
*
* @param Doctrine\DBAL\Connection $conn
* @return string $database
*/
public function getDatabase(\Doctrine\DBAL\Connection $conn)
{
$params = $conn->getParams();
return $params['dbname'];
}
}
<?php
/*
* $Id: Interface.php 3882 2008-02-22 18:11:35Z jwage $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver;
/**
* The PDO implementation of the Statement interface.
* Used by all PDO-based drivers.
*
* @since 2.0
*/
class PDOStatement extends \PDOStatement implements Statement
{
private function __construct() {}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\PDOMsSql;
/**
* The PDO-based MsSql driver.
*
* @since 2.0
*/
class Driver implements \Doctrine\DBAL\Driver
{
public function connect(array $params, $username = null, $password = null, array $driverOptions = array())
{
return new Connection(
$this->_constructPdoDsn($params),
$username,
$password,
$driverOptions
);
}
/**
* Constructs the MsSql PDO DSN.
*
* @return string The DSN.
*/
private function _constructPdoDsn(array $params)
{
// TODO: This might need to be revisted once we have access to a mssql server
$dsn = 'mssql:';
if (isset($params['host'])) {
$dsn .= 'host=' . $params['host'] . ';';
}
if (isset($params['port'])) {
$dsn .= 'port=' . $params['port'] . ';';
}
if (isset($params['dbname'])) {
$dsn .= 'dbname=' . $params['dbname'] . ';';
}
return $dsn;
}
public function getDatabasePlatform()
{
return new \Doctrine\DBAL\Platforms\MsSqlPlatform();
}
public function getSchemaManager(\Doctrine\DBAL\Connection $conn)
{
return new \Doctrine\DBAL\Schema\MsSqlSchemaManager($conn);
}
public function getName()
{
return 'pdo_mssql';
}
public function getDatabase(\Doctrine\DBAL\Connection $conn)
{
$params = $conn->getParams();
return $params['dbname'];
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\PDOMsSql;
/**
* MsSql Connection implementation.
*
* @since 2.0
*/
class Connection extends \PDO implements \Doctrine\DBAL\Driver\Connection
{
/**
* Performs the rollback.
*
* @override
*/
public function rollback()
{
$this->exec('ROLLBACK TRANSACTION');
}
/**
* Performs the commit.
*
* @override
*/
public function commit()
{
$this->exec('COMMIT TRANSACTION');
}
/**
* Begins a database transaction.
*
* @override
*/
public function beginTransaction()
{
$this->exec('BEGIN TRANSACTION');
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver;
use \PDO;
/**
* Statement interface.
* Drivers must implement this interface.
*
* This resembles (a subset of) the PDOStatement interface.
*
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Roman Borschel <roman@code-factory.org>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
*/
interface Statement
{
/**
* Binds a value to a corresponding named or positional
* placeholder in the SQL statement that was used to prepare the statement.
*
* @param mixed $param Parameter identifier. For a prepared statement using named placeholders,
* this will be a parameter name of the form :name. For a prepared statement
* using question mark placeholders, this will be the 1-indexed position of the parameter
*
* @param mixed $value The value to bind to the parameter.
* @param integer $type Explicit data type for the parameter using the PDO::PARAM_* constants.
*
* @return boolean Returns TRUE on success or FALSE on failure.
*/
function bindValue($param, $value, $type = null);
/**
* Binds a PHP variable to a corresponding named or question mark placeholder in the
* SQL statement that was use to prepare the statement. Unlike PDOStatement->bindValue(),
* the variable is bound as a reference and will only be evaluated at the time
* that PDOStatement->execute() is called.
*
* Most parameters are input parameters, that is, parameters that are
* used in a read-only fashion to build up the query. Some drivers support the invocation
* of stored procedures that return data as output parameters, and some also as input/output
* parameters that both send in data and are updated to receive it.
*
* @param mixed $param Parameter identifier. For a prepared statement using named placeholders,
* this will be a parameter name of the form :name. For a prepared statement
* using question mark placeholders, this will be the 1-indexed position of the parameter
*
* @param mixed $variable Name of the PHP variable to bind to the SQL statement parameter.
*
* @param integer $type Explicit data type for the parameter using the PDO::PARAM_* constants. To return
* an INOUT parameter from a stored procedure, use the bitwise OR operator to set the
* PDO::PARAM_INPUT_OUTPUT bits for the data_type parameter.
* @return boolean Returns TRUE on success or FALSE on failure.
*/
function bindParam($column, &$variable, $type = null);
/**
* Closes the cursor, enabling the statement to be executed again.
*
* @return boolean Returns TRUE on success or FALSE on failure.
*/
function closeCursor();
/**
* columnCount
* Returns the number of columns in the result set
*
* @return integer Returns the number of columns in the result set represented
* by the PDOStatement object. If there is no result set,
* this method should return 0.
*/
function columnCount();
/**
* errorCode
* Fetch the SQLSTATE associated with the last operation on the statement handle
*
* @see Doctrine_Adapter_Interface::errorCode()
* @return string error code string
*/
function errorCode();
/**
* errorInfo
* Fetch extended error information associated with the last operation on the statement handle
*
* @see Doctrine_Adapter_Interface::errorInfo()
* @return array error info array
*/
function errorInfo();
/**
* Executes a prepared statement
*
* If the prepared statement included parameter markers, you must either:
* call PDOStatement->bindParam() to bind PHP variables to the parameter markers:
* bound variables pass their value as input and receive the output value,
* if any, of their associated parameter markers or pass an array of input-only
* parameter values
*
*
* @param array $params An array of values with as many elements as there are
* bound parameters in the SQL statement being executed.
* @return boolean Returns TRUE on success or FALSE on failure.
*/
function execute($params = null);
/**
* fetch
*
* @see Query::HYDRATE_* constants
* @param integer $fetchStyle Controls how the next row will be returned to the caller.
* This value must be one of the Query::HYDRATE_* constants,
* defaulting to Query::HYDRATE_BOTH
*
* @param integer $cursorOrientation For a PDOStatement object representing a scrollable cursor,
* this value determines which row will be returned to the caller.
* This value must be one of the Query::HYDRATE_ORI_* constants, defaulting to
* Query::HYDRATE_ORI_NEXT. To request a scrollable cursor for your
* PDOStatement object,
* you must set the PDO::ATTR_CURSOR attribute to Doctrine::CURSOR_SCROLL when you
* prepare the SQL statement with Doctrine_Adapter_Interface->prepare().
*
* @param integer $cursorOffset For a PDOStatement object representing a scrollable cursor for which the
* $cursorOrientation parameter is set to Query::HYDRATE_ORI_ABS, this value specifies
* the absolute number of the row in the result set that shall be fetched.
*
* For a PDOStatement object representing a scrollable cursor for
* which the $cursorOrientation parameter is set to Query::HYDRATE_ORI_REL, this value
* specifies the row to fetch relative to the cursor position before
* PDOStatement->fetch() was called.
*
* @return mixed
*/
function fetch($fetchStyle = PDO::FETCH_BOTH);
/**
* Returns an array containing all of the result set rows
*
* @param integer $fetchStyle Controls how the next row will be returned to the caller.
* This value must be one of the Query::HYDRATE_* constants,
* defaulting to Query::HYDRATE_BOTH
*
* @param integer $columnIndex Returns the indicated 0-indexed column when the value of $fetchStyle is
* Query::HYDRATE_COLUMN. Defaults to 0.
*
* @return array
*/
function fetchAll($fetchStyle = PDO::FETCH_BOTH);
/**
* fetchColumn
* Returns a single column from the next row of a
* result set or FALSE if there are no more rows.
*
* @param integer $columnIndex 0-indexed number of the column you wish to retrieve from the row. If no
* value is supplied, PDOStatement->fetchColumn()
* fetches the first column.
*
* @return string returns a single column in the next row of a result set.
*/
function fetchColumn($columnIndex = 0);
/**
* rowCount
* rowCount() returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement
* executed by the corresponding object.
*
* If the last SQL statement executed by the associated Statement object was a SELECT statement,
* some databases may return the number of rows returned by that statement. However,
* this behaviour is not guaranteed for all databases and should not be
* relied on for portable applications.
*
* @return integer Returns the number of rows.
*/
function rowCount();
}<?php
namespace Doctrine\DBAL\Driver\PDOPgSql;
use Doctrine\DBAL\Platforms;
/**
* Driver that connects through pdo_pgsql.
*
* @since 2.0
*/
class Driver implements \Doctrine\DBAL\Driver
{
/**
* Attempts to connect to the database and returns a driver connection on success.
*
* @return Doctrine\DBAL\Driver\Connection
*/
public function connect(array $params, $username = null, $password = null, array $driverOptions = array())
{
return new \Doctrine\DBAL\Driver\PDOConnection(
$this->_constructPdoDsn($params),
$username,
$password,
$driverOptions
);
}
/**
* Constructs the Postgres PDO DSN.
*
* @return string The DSN.
*/
private function _constructPdoDsn(array $params)
{
$dsn = 'pgsql:';
if (isset($params['host'])) {
$dsn .= 'host=' . $params['host'] . ' ';
}
if (isset($params['port'])) {
$dsn .= 'port=' . $params['port'] . ' ';
}
if (isset($params['dbname'])) {
$dsn .= 'dbname=' . $params['dbname'] . ' ';
}
return $dsn;
}
public function getDatabasePlatform()
{
return new \Doctrine\DBAL\Platforms\PostgreSqlPlatform();
}
public function getSchemaManager(\Doctrine\DBAL\Connection $conn)
{
return new \Doctrine\DBAL\Schema\PostgreSqlSchemaManager($conn);
}
public function getName()
{
return 'pdo_pgsql';
}
public function getDatabase(\Doctrine\DBAL\Connection $conn)
{
$params = $conn->getParams();
return $params['dbname'];
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver;
use \PDO;
/**
* PDO implementation of the Connection interface.
* Used by all PDO-based drivers.
*
* @since 2.0
*/
class PDOConnection extends PDO implements Connection
{
public function __construct($dsn, $user = null, $password = null, array $options = null)
{
parent::__construct($dsn, $user, $password, $options);
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('Doctrine\DBAL\Driver\PDOStatement', array()));
$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\PDOIbm;
use Doctrine\DBAL\Connection;
/**
* Driver for the PDO IBM extension
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 1.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class Driver implements \Doctrine\DBAL\Driver
{
/**
* Attempts to establish a connection with the underlying driver.
*
* @param array $params
* @param string $username
* @param string $password
* @param array $driverOptions
* @return Doctrine\DBAL\Driver\Connection
*/
public function connect(array $params, $username = null, $password = null, array $driverOptions = array())
{
$conn = new \Doctrine\DBAL\Driver\PDOConnection(
$this->_constructPdoDsn($params),
$username,
$password,
$driverOptions
);
return $conn;
}
/**
* Constructs the MySql PDO DSN.
*
* @return string The DSN.
*/
private function _constructPdoDsn(array $params)
{
$dsn = 'ibm:';
if (isset($params['host'])) {
$dsn .= 'HOSTNAME=' . $params['host'] . ';';
}
if (isset($params['port'])) {
$dsn .= 'PORT=' . $params['port'] . ';';
}
$dsn .= 'PROTOCOL=TCPIP;';
if (isset($params['dbname'])) {
$dsn .= 'DATABASE=' . $params['dbname'] . ';';
}
return $dsn;
}
/**
* Gets the DatabasePlatform instance that provides all the metadata about
* the platform this driver connects to.
*
* @return Doctrine\DBAL\Platforms\AbstractPlatform The database platform.
*/
public function getDatabasePlatform()
{
return new \Doctrine\DBAL\Platforms\DB2Platform;
}
/**
* Gets the SchemaManager that can be used to inspect and change the underlying
* database schema of the platform this driver connects to.
*
* @param Doctrine\DBAL\Connection $conn
* @return Doctrine\DBAL\SchemaManager
*/
public function getSchemaManager(Connection $conn)
{
return new \Doctrine\DBAL\Schema\DB2SchemaManager($conn);
}
/**
* Gets the name of the driver.
*
* @return string The name of the driver.
*/
public function getName()
{
return 'pdo_ibm';
}
/**
* Get the name of the database connected to for this driver.
*
* @param Doctrine\DBAL\Connection $conn
* @return string $database
*/
public function getDatabase(\Doctrine\DBAL\Connection $conn)
{
$params = $conn->getParams();
return $params['dbname'];
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\PDOMySql;
use Doctrine\DBAL\Connection;
/**
* PDO MySql driver.
*
* @since 2.0
*/
class Driver implements \Doctrine\DBAL\Driver
{
/**
* Attempts to establish a connection with the underlying driver.
*
* @param array $params
* @param string $username
* @param string $password
* @param array $driverOptions
* @return Doctrine\DBAL\Driver\Connection
*/
public function connect(array $params, $username = null, $password = null, array $driverOptions = array())
{
$conn = new \Doctrine\DBAL\Driver\PDOConnection(
$this->_constructPdoDsn($params),
$username,
$password,
$driverOptions
);
return $conn;
}
/**
* Constructs the MySql PDO DSN.
*
* @return string The DSN.
*/
private function _constructPdoDsn(array $params)
{
$dsn = 'mysql:';
if (isset($params['host'])) {
$dsn .= 'host=' . $params['host'] . ';';
}
if (isset($params['port'])) {
$dsn .= 'port=' . $params['port'] . ';';
}
if (isset($params['dbname'])) {
$dsn .= 'dbname=' . $params['dbname'] . ';';
}
if (isset($params['unix_socket'])) {
$dsn .= 'unix_socket=' . $params['unix_socket'] . ';';
}
return $dsn;
}
public function getDatabasePlatform()
{
return new \Doctrine\DBAL\Platforms\MySqlPlatform();
}
public function getSchemaManager(\Doctrine\DBAL\Connection $conn)
{
return new \Doctrine\DBAL\Schema\MySqlSchemaManager($conn);
}
public function getName()
{
return 'pdo_mysql';
}
public function getDatabase(\Doctrine\DBAL\Connection $conn)
{
$params = $conn->getParams();
return $params['dbname'];
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\PDOSqlsrv;
/**
* The PDO-based Sqlsrv driver.
*
* @since 2.0
*/
class Driver implements \Doctrine\DBAL\Driver
{
public function connect(array $params, $username = null, $password = null, array $driverOptions = array())
{
return new \Doctrine\DBAL\Driver\PDOConnection(
$this->_constructPdoDsn($params),
$username,
$password,
$driverOptions
);
}
/**
* Constructs the Sqlsrv PDO DSN.
*
* @return string The DSN.
*/
private function _constructPdoDsn(array $params)
{
$dsn = 'sqlsrv:server=';
if (isset($params['host'])) {
$dsn .= $params['host'];
}
if (isset($params['port']) && !empty($params['port'])) {
$dsn .= ',' . $params['port'];
}
if (isset($params['dbname'])) {
$dsn .= ';Database=' . $params['dbname'];
}
return $dsn;
}
public function getDatabasePlatform()
{
return new \Doctrine\DBAL\Platforms\MsSqlPlatform();
}
public function getSchemaManager(\Doctrine\DBAL\Connection $conn)
{
return new \Doctrine\DBAL\Schema\MsSqlSchemaManager($conn);
}
public function getName()
{
return 'pdo_sqlsrv';
}
public function getDatabase(\Doctrine\DBAL\Connection $conn)
{
$params = $conn->getParams();
return $params['dbname'];
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\PDOSqlite;
/**
* The PDO Sqlite driver.
*
* @since 2.0
*/
class Driver implements \Doctrine\DBAL\Driver
{
/**
* @var array
*/
protected $_userDefinedFunctions = array(
'sqrt' => array('callback' => array('Doctrine\DBAL\Platforms\SqlitePlatform', 'udfSqrt'), 'numArgs' => 1),
'mod' => array('callback' => array('Doctrine\DBAL\Platforms\SqlitePlatform', 'udfMod'), 'numArgs' => 2),
'locate' => array('callback' => array('Doctrine\DBAL\Platforms\SqlitePlatform', 'udfLocate'), 'numArgs' => -1),
);
/**
* Tries to establish a database connection to SQLite.
*
* @param array $params
* @param string $username
* @param string $password
* @param array $driverOptions
* @return Connection
*/
public function connect(array $params, $username = null, $password = null, array $driverOptions = array())
{
if (isset($driverOptions['userDefinedFunctions'])) {
$this->_userDefinedFunctions = array_merge(
$this->_userDefinedFunctions, $driverOptions['userDefinedFunctions']);
unset($driverOptions['userDefinedFunctions']);
}
$pdo = new \Doctrine\DBAL\Driver\PDOConnection(
$this->_constructPdoDsn($params),
$username,
$password,
$driverOptions
);
foreach ($this->_userDefinedFunctions AS $fn => $data) {
$pdo->sqliteCreateFunction($fn, $data['callback'], $data['numArgs']);
}
return $pdo;
}
/**
* Constructs the Sqlite PDO DSN.
*
* @return string The DSN.
* @override
*/
protected function _constructPdoDsn(array $params)
{
$dsn = 'sqlite:';
if (isset($params['path'])) {
$dsn .= $params['path'];
} else if (isset($params['memory'])) {
$dsn .= ':memory:';
}
return $dsn;
}
/**
* Gets the database platform that is relevant for this driver.
*/
public function getDatabasePlatform()
{
return new \Doctrine\DBAL\Platforms\SqlitePlatform();
}
/**
* Gets the schema manager that is relevant for this driver.
*
* @param Doctrine\DBAL\Connection $conn
* @return Doctrine\DBAL\Schema\SqliteSchemaManager
*/
public function getSchemaManager(\Doctrine\DBAL\Connection $conn)
{
return new \Doctrine\DBAL\Schema\SqliteSchemaManager($conn);
}
public function getName()
{
return 'pdo_sqlite';
}
public function getDatabase(\Doctrine\DBAL\Connection $conn)
{
$params = $conn->getParams();
return isset($params['path']) ? $params['path'] : null;
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\OCI8;
class OCI8Exception extends \Exception
{
static public function fromErrorInfo($error)
{
return new self($error['message'], $error['code']);
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\OCI8;
use Doctrine\DBAL\Platforms;
/**
* A Doctrine DBAL driver for the Oracle OCI8 PHP extensions.
*
* @author Roman Borschel <roman@code-factory.org>
* @since 2.0
*/
class Driver implements \Doctrine\DBAL\Driver
{
public function connect(array $params, $username = null, $password = null, array $driverOptions = array())
{
return new OCI8Connection(
$username,
$password,
$this->_constructDsn($params)
);
}
/**
* Constructs the Oracle DSN.
*
* @return string The DSN.
*/
private function _constructDsn(array $params)
{
$dsn = '';
if (isset($params['host'])) {
$dsn .= '(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)' .
'(HOST=' . $params['host'] . ')';
if (isset($params['port'])) {
$dsn .= '(PORT=' . $params['port'] . ')';
} else {
$dsn .= '(PORT=1521)';
}
$dsn .= '))';
if (isset($params['dbname'])) {
$dsn .= '(CONNECT_DATA=(SID=' . $params['dbname'] . ')';
}
$dsn .= '))';
} else {
$dsn .= $params['dbname'];
}
if (isset($params['charset'])) {
$dsn .= ';charset=' . $params['charset'];
}
return $dsn;
}
public function getDatabasePlatform()
{
return new \Doctrine\DBAL\Platforms\OraclePlatform();
}
public function getSchemaManager(\Doctrine\DBAL\Connection $conn)
{
return new \Doctrine\DBAL\Schema\OracleSchemaManager($conn);
}
public function getName()
{
return 'oci8';
}
public function getDatabase(\Doctrine\DBAL\Connection $conn)
{
$params = $conn->getParams();
return $params['user'];
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\OCI8;
use \PDO;
/**
* The OCI8 implementation of the Statement interface.
*
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
*/
class OCI8Statement implements \Doctrine\DBAL\Driver\Statement
{
/** Statement handle. */
private $_sth;
private static $_PARAM = ':param';
private static $fetchStyleMap = array(
PDO::FETCH_BOTH => OCI_BOTH,
PDO::FETCH_ASSOC => OCI_ASSOC,
PDO::FETCH_NUM => OCI_NUM
);
private $_paramMap = array();
/**
* Creates a new OCI8Statement that uses the given connection handle and SQL statement.
*
* @param resource $dbh The connection handle.
* @param string $statement The SQL statement.
*/
public function __construct($dbh, $statement)
{
list($statement, $paramMap) = self::convertPositionalToNamedPlaceholders($statement);
$this->_sth = oci_parse($dbh, $statement);
$this->_paramMap = $paramMap;
}
/**
* Convert positional (?) into named placeholders (:param<num>)
*
* Oracle does not support positional parameters, hence this method converts all
* positional parameters into artificially named parameters. Note that this conversion
* is not perfect. All question marks (?) in the original statement are treated as
* placeholders and converted to a named parameter.
*
* The algorithm uses a state machine with two possible states: InLiteral and NotInLiteral.
* Question marks inside literal strings are therefore handled correctly by this method.
* This comes at a cost, the whole sql statement has to be looped over.
*
* @todo extract into utility class in Doctrine\DBAL\Util namespace
* @todo review and test for lost spaces. we experienced missing spaces with oci8 in some sql statements.
* @param string $statement The SQL statement to convert.
* @return string
*/
static public function convertPositionalToNamedPlaceholders($statement)
{
$count = 1;
$inLiteral = false; // a valid query never starts with quotes
$stmtLen = strlen($statement);
$paramMap = array();
for ($i = 0; $i < $stmtLen; $i++) {
if ($statement[$i] == '?' && !$inLiteral) {
// real positional parameter detected
$paramMap[$count] = ":param$count";
$len = strlen($paramMap[$count]);
$statement = substr_replace($statement, ":param$count", $i, 1);
$i += $len-1; // jump ahead
$stmtLen = strlen($statement); // adjust statement length
++$count;
} else if ($statement[$i] == "'" || $statement[$i] == '"') {
$inLiteral = ! $inLiteral; // switch state!
}
}
return array($statement, $paramMap);
}
/**
* {@inheritdoc}
*/
public function bindValue($param, $value, $type = null)
{
return $this->bindParam($param, $value, $type);
}
/**
* {@inheritdoc}
*/
public function bindParam($column, &$variable, $type = null)
{
$column = isset($this->_paramMap[$column]) ? $this->_paramMap[$column] : $column;
return oci_bind_by_name($this->_sth, $column, $variable);
}
/**
* Closes the cursor, enabling the statement to be executed again.
*
* @return boolean Returns TRUE on success or FALSE on failure.
*/
public function closeCursor()
{
return oci_free_statement($this->_sth);
}
/**
* {@inheritdoc}
*/
public function columnCount()
{
return oci_num_fields($this->_sth);
}
/**
* {@inheritdoc}
*/
public function errorCode()
{
$error = oci_error($this->_sth);
if ($error !== false) {
$error = $error['code'];
}
return $error;
}
/**
* {@inheritdoc}
*/
public function errorInfo()
{
return oci_error($this->_sth);
}
/**
* {@inheritdoc}
*/
public function execute($params = null)
{
if ($params) {
$hasZeroIndex = isset($params[0]);
foreach ($params as $key => $val) {
if ($hasZeroIndex && is_numeric($key)) {
$this->bindValue($key + 1, $val);
} else {
$this->bindValue($key, $val);
}
}
}
$ret = @oci_execute($this->_sth, OCI_DEFAULT);
if ( ! $ret) {
throw OCI8Exception::fromErrorInfo($this->errorInfo());
}
return $ret;
}
/**
* {@inheritdoc}
*/
public function fetch($fetchStyle = PDO::FETCH_BOTH)
{
if ( ! isset(self::$fetchStyleMap[$fetchStyle])) {
throw new \InvalidArgumentException("Invalid fetch style: " . $fetchStyle);
}
return oci_fetch_array($this->_sth, self::$fetchStyleMap[$fetchStyle] | OCI_RETURN_NULLS | OCI_RETURN_LOBS);
}
/**
* {@inheritdoc}
*/
public function fetchAll($fetchStyle = PDO::FETCH_BOTH)
{
if ( ! isset(self::$fetchStyleMap[$fetchStyle])) {
throw new \InvalidArgumentException("Invalid fetch style: " . $fetchStyle);
}
$result = array();
oci_fetch_all($this->_sth, $result, 0, -1,
self::$fetchStyleMap[$fetchStyle] | OCI_RETURN_NULLS | OCI_FETCHSTATEMENT_BY_ROW | OCI_RETURN_LOBS);
return $result;
}
/**
* {@inheritdoc}
*/
public function fetchColumn($columnIndex = 0)
{
$row = oci_fetch_array($this->_sth, OCI_NUM | OCI_RETURN_NULLS | OCI_RETURN_LOBS);
return $row[$columnIndex];
}
/**
* {@inheritdoc}
*/
public function rowCount()
{
return oci_num_rows($this->_sth);
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\OCI8;
/**
* OCI8 implementation of the Connection interface.
*
* @since 2.0
*/
class OCI8Connection implements \Doctrine\DBAL\Driver\Connection
{
private $_dbh;
/**
* Create a Connection to an Oracle Database using oci8 extension.
*
* @param string $username
* @param string $password
* @param string $db
*/
public function __construct($username, $password, $db)
{
$this->_dbh = @oci_connect($username, $password, $db);
if (!$this->_dbh) {
throw new OCI8Exception($this->errorInfo());
}
}
/**
* Create a non-executed prepared statement.
*
* @param string $prepareString
* @return OCI8Statement
*/
public function prepare($prepareString)
{
return new OCI8Statement($this->_dbh, $prepareString);
}
/**
* @param string $sql
* @return OCI8Statement
*/
public function query()
{
$args = func_get_args();
$sql = $args[0];
//$fetchMode = $args[1];
$stmt = $this->prepare($sql);
$stmt->execute();
return $stmt;
}
/**
* Quote input value.
*
* @param mixed $input
* @param int $type PDO::PARAM*
* @return mixed
*/
public function quote($input, $type=\PDO::PARAM_STR)
{
return is_numeric($input) ? $input : "'$input'";
}
/**
*
* @param string $statement
* @return int
*/
public function exec($statement)
{
$stmt = $this->prepare($statement);
$stmt->execute();
return $stmt->rowCount();
}
public function lastInsertId($name = null)
{
//TODO: throw exception or support sequences?
}
/**
* Start a transactiom
*
* Oracle has to explicitly set the autocommit mode off. That means
* after connection, a commit or rollback there is always automatically
* opened a new transaction.
*
* @return bool
*/
public function beginTransaction()
{
return true;
}
/**
* @throws OCI8Exception
* @return bool
*/
public function commit()
{
if (!oci_commit($this->_dbh)) {
throw OCI8Exception::fromErrorInfo($this->errorInfo());
}
return true;
}
/**
* @throws OCI8Exception
* @return bool
*/
public function rollBack()
{
if (!oci_rollback($this->_dbh)) {
throw OCI8Exception::fromErrorInfo($this->errorInfo());
}
return true;
}
public function errorCode()
{
$error = oci_error($this->_dbh);
if ($error !== false) {
$error = $error['code'];
}
return $error;
}
public function errorInfo()
{
return oci_error($this->_dbh);
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver;
/**
* Connection interface.
* Driver connections must implement this interface.
*
* This resembles (a subset of) the PDO interface.
*
* @since 2.0
*/
interface Connection
{
function prepare($prepareString);
function query();
function quote($input, $type=\PDO::PARAM_STR);
function exec($statement);
function lastInsertId($name = null);
function beginTransaction();
function commit();
function rollBack();
function errorCode();
function errorInfo();
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL;
/**
* Container for all DBAL events.
*
* This class cannot be instantiated.
*
* @author Roman Borschel <roman@code-factory.org>
* @since 2.0
*/
final class Events
{
private function __construct() {}
const postConnect = 'postConnect';
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL;
use Doctrine\Common\EventManager;
/**
* Factory for creating Doctrine\DBAL\Connection instances.
*
* @author Roman Borschel <roman@code-factory.org>
* @since 2.0
*/
final class DriverManager
{
/**
* List of supported drivers and their mappings to the driver classes.
*
* @var array
* @todo REMOVE. Users should directly supply class names instead.
*/
private static $_driverMap = array(
'pdo_mysql' => 'Doctrine\DBAL\Driver\PDOMySql\Driver',
'pdo_sqlite' => 'Doctrine\DBAL\Driver\PDOSqlite\Driver',
'pdo_pgsql' => 'Doctrine\DBAL\Driver\PDOPgSql\Driver',
'pdo_oci' => 'Doctrine\DBAL\Driver\PDOOracle\Driver',
'pdo_mssql' => 'Doctrine\DBAL\Driver\PDOMsSql\Driver',
'oci8' => 'Doctrine\DBAL\Driver\OCI8\Driver',
'ibm_db2' => 'Doctrine\DBAL\Driver\IBMDB2\DB2Driver',
'pdo_ibm' => 'Doctrine\DBAL\Driver\PDOIbm\Driver',
'pdo_sqlsrv' => 'Doctrine\DBAL\Driver\PDOSqlsrv\Driver',
);
/** Private constructor. This class cannot be instantiated. */
private function __construct() { }
/**
* Creates a connection object based on the specified parameters.
* This method returns a Doctrine\DBAL\Connection which wraps the underlying
* driver connection.
*
* $params must contain at least one of the following.
*
* Either 'driver' with one of the following values:
* pdo_mysql
* pdo_sqlite
* pdo_pgsql
* pdo_oracle
* pdo_mssql
*
* OR 'driverClass' that contains the full class name (with namespace) of the
* driver class to instantiate.
*
* Other (optional) parameters:
*
* <b>user (string)</b>:
* The username to use when connecting.
*
* <b>password (string)</b>:
* The password to use when connecting.
*
* <b>driverOptions (array)</b>:
* Any additional driver-specific options for the driver. These are just passed
* through to the driver.
*
* <b>pdo</b>:
* You can pass an existing PDO instance through this parameter. The PDO
* instance will be wrapped in a Doctrine\DBAL\Connection.
*
* <b>wrapperClass</b>:
* You may specify a custom wrapper class through the 'wrapperClass'
* parameter but this class MUST inherit from Doctrine\DBAL\Connection.
*
* @param array $params The parameters.
* @param Doctrine\DBAL\Configuration The configuration to use.
* @param Doctrine\Common\EventManager The event manager to use.
* @return Doctrine\DBAL\Connection
*/
public static function getConnection(
array $params,
Configuration $config = null,
EventManager $eventManager = null)
{
// create default config and event manager, if not set
if ( ! $config) {
$config = new Configuration();
}
if ( ! $eventManager) {
$eventManager = new EventManager();
}
// check for existing pdo object
if (isset($params['pdo']) && ! $params['pdo'] instanceof \PDO) {
throw DBALException::invalidPdoInstance();
} else if (isset($params['pdo'])) {
$params['pdo']->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$params['driver'] = 'pdo_' . $params['pdo']->getAttribute(\PDO::ATTR_DRIVER_NAME);
} else {
self::_checkParams($params);
}
if (isset($params['driverClass'])) {
$className = $params['driverClass'];
} else {
$className = self::$_driverMap[$params['driver']];
}
$driver = new $className();
$wrapperClass = 'Doctrine\DBAL\Connection';
if (isset($params['wrapperClass'])) {
if (is_subclass_of($params['wrapperClass'], $wrapperClass)) {
$wrapperClass = $params['wrapperClass'];
} else {
throw DBALException::invalidWrapperClass($params['wrapperClass']);
}
}
return new $wrapperClass($params, $driver, $config, $eventManager);
}
/**
* Checks the list of parameters.
*
* @param array $params
*/
private static function _checkParams(array $params)
{
// check existance of mandatory parameters
// driver
if ( ! isset($params['driver']) && ! isset($params['driverClass'])) {
throw DBALException::driverRequired();
}
// check validity of parameters
// driver
if ( isset($params['driver']) && ! isset(self::$_driverMap[$params['driver']])) {
throw DBALException::unknownDriver($params['driver'], array_keys(self::$_driverMap));
}
if (isset($params['driverClass']) && ! in_array('Doctrine\DBAL\Driver', class_implements($params['driverClass'], true))) {
throw DBALException::invalidDriverClass($params['driverClass']);
}
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL;
use Doctrine\DBAL\Logging\SQLLogger;
/**
* Configuration container for the Doctrine DBAL.
*
* @since 2.0
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @internal When adding a new configuration option just write a getter/setter
* pair and add the option to the _attributes array with a proper default value.
*/
class Configuration
{
/**
* The attributes that are contained in the configuration.
* Values are default values.
*
* @var array
*/
protected $_attributes = array();
/**
* Sets the SQL logger to use. Defaults to NULL which means SQL logging is disabled.
*
* @param SQLLogger $logger
*/
public function setSQLLogger(SQLLogger $logger)
{
$this->_attributes['sqlLogger'] = $logger;
}
/**
* Gets the SQL logger that is used.
*
* @return SQLLogger
*/
public function getSQLLogger()
{
return isset($this->_attributes['sqlLogger']) ?
$this->_attributes['sqlLogger'] : null;
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL;
use PDO,
Doctrine\DBAL\Types\Type,
Doctrine\DBAL\Driver\Statement as DriverStatement;
/**
* A thin wrapper around a Doctrine\DBAL\Driver\Statement that adds support
* for logging, DBAL mapping types, etc.
*
* @author Roman Borschel <roman@code-factory.org>
* @since 2.0
*/
class Statement implements DriverStatement
{
/**
* @var string The SQL statement.
*/
private $_sql;
/**
* @var array The bound parameters.
*/
private $_params = array();
/**
* @var Doctrine\DBAL\Driver\Statement The underlying driver statement.
*/
private $_stmt;
/**
* @var Doctrine\DBAL\Platforms\AbstractPlatform The underlying database platform.
*/
private $_platform;
/**
* @var Doctrine\DBAL\Connection The connection this statement is bound to and executed on.
*/
private $_conn;
/**
* Creates a new <tt>Statement</tt> for the given SQL and <tt>Connection</tt>.
*
* @param string $sql The SQL of the statement.
* @param Doctrine\DBAL\Connection The connection on which the statement should be executed.
*/
public function __construct($sql, Connection $conn)
{
$this->_sql = $sql;
$this->_stmt = $conn->getWrappedConnection()->prepare($sql);
$this->_conn = $conn;
$this->_platform = $conn->getDatabasePlatform();
}
/**
* Binds a parameter value to the statement.
*
* The value can optionally be bound with a PDO binding type or a DBAL mapping type.
* If bound with a DBAL mapping type, the binding type is derived from the mapping
* type and the value undergoes the conversion routines of the mapping type before
* being bound.
*
* @param $name The name or position of the parameter.
* @param $value The value of the parameter.
* @param mixed $type Either a PDO binding type or a DBAL mapping type name or instance.
* @return boolean TRUE on success, FALSE on failure.
*/
public function bindValue($name, $value, $type = null)
{
$this->_params[$name] = $value;
if ($type !== null) {
if (is_string($type)) {
$type = Type::getType($type);
}
if ($type instanceof Type) {
$value = $type->convertToDatabaseValue($value, $this->_platform);
$bindingType = $type->getBindingType();
} else {
$bindingType = $type; // PDO::PARAM_* constants
}
return $this->_stmt->bindValue($name, $value, $bindingType);
} else {
return $this->_stmt->bindValue($name, $value);
}
}
/**
* Binds a parameter to a value by reference.
*
* Binding a parameter by reference does not support DBAL mapping types.
*
* @param string $name The name or position of the parameter.
* @param mixed $value The reference to the variable to bind
* @param integer $type The PDO binding type.
* @return boolean TRUE on success, FALSE on failure.
*/
public function bindParam($name, &$var, $type = PDO::PARAM_STR)
{
return $this->_stmt->bindParam($name, $var, $type);
}
/**
* Executes the statement with the currently bound parameters.
*
* @return boolean TRUE on success, FALSE on failure.
*/
public function execute($params = null)
{
$hasLogger = $this->_conn->getConfiguration()->getSQLLogger();
if ($hasLogger) {
$this->_conn->getConfiguration()->getSQLLogger()->startQuery($this->_sql, $this->_params);
}
$stmt = $this->_stmt->execute($params);
if ($hasLogger) {
$this->_conn->getConfiguration()->getSQLLogger()->stopQuery();
}
$this->_params = array();
return $stmt;
}
/**
* Closes the cursor, freeing the database resources used by this statement.
*
* @return boolean TRUE on success, FALSE on failure.
*/
public function closeCursor()
{
return $this->_stmt->closeCursor();
}
/**
* Returns the number of columns in the result set.
*
* @return integer
*/
public function columnCount()
{
return $this->_stmt->columnCount();
}
/**
* Fetches the SQLSTATE associated with the last operation on the statement.
*
* @return string
*/
public function errorCode()
{
return $this->_stmt->errorCode();
}
/**
* Fetches extended error information associated with the last operation on the statement.
*
* @return array
*/
public function errorInfo()
{
return $this->_stmt->errorInfo();
}
/**
* Fetches the next row from a result set.
*
* @param integer $fetchStyle
* @return mixed The return value of this function on success depends on the fetch type.
* In all cases, FALSE is returned on failure.
*/
public function fetch($fetchStyle = PDO::FETCH_BOTH)
{
return $this->_stmt->fetch($fetchStyle);
}
/**
* Returns an array containing all of the result set rows.
*
* @param integer $fetchStyle
* @param integer $columnIndex
* @return array An array containing all of the remaining rows in the result set.
*/
public function fetchAll($fetchStyle = PDO::FETCH_BOTH, $columnIndex = 0)
{
if ($columnIndex != 0) {
return $this->_stmt->fetchAll($fetchStyle, $columnIndex);
}
return $this->_stmt->fetchAll($fetchStyle);
}
/**
* Returns a single column from the next row of a result set.
*
* @param integer $columnIndex
* @return mixed A single column from the next row of a result set or FALSE if there are no more rows.
*/
public function fetchColumn($columnIndex = 0)
{
return $this->_stmt->fetchColumn($columnIndex);
}
/**
* Returns the number of rows affected by the last execution of this statement.
*
* @return integer The number of affected rows.
*/
public function rowCount()
{
return $this->_stmt->rowCount();
}
/**
* Gets the wrapped driver statement.
*
* @return Doctrine\DBAL\Driver\Statement
*/
public function getWrappedStatement()
{
return $this->_stmt;
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* Schema manager for the MySql RDBMS.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Roman Borschel <roman@code-factory.org>
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @version $Revision$
* @since 2.0
*/
class MySqlSchemaManager extends AbstractSchemaManager
{
protected function _getPortableViewDefinition($view)
{
return new View($view['TABLE_NAME'], $view['VIEW_DEFINITION']);
}
protected function _getPortableTableDefinition($table)
{
return array_shift($table);
}
protected function _getPortableUserDefinition($user)
{
return array(
'user' => $user['User'],
'password' => $user['Password'],
);
}
protected function _getPortableTableIndexesList($tableIndexes, $tableName=null)
{
foreach($tableIndexes AS $k => $v) {
$v = array_change_key_case($v, CASE_LOWER);
if($v['key_name'] == 'PRIMARY') {
$v['primary'] = true;
} else {
$v['primary'] = false;
}
$tableIndexes[$k] = $v;
}
return parent::_getPortableTableIndexesList($tableIndexes, $tableName);
}
protected function _getPortableSequenceDefinition($sequence)
{
return end($sequence);
}
protected function _getPortableDatabaseDefinition($database)
{
return $database['Database'];
}
/**
* Gets a portable column definition.
*
* The database type is mapped to a corresponding Doctrine mapping type.
*
* @param $tableColumn
* @return array
*/
protected function _getPortableTableColumnDefinition($tableColumn)
{
$tableColumn = array_change_key_case($tableColumn, CASE_LOWER);
$dbType = strtolower($tableColumn['type']);
$dbType = strtok($dbType, '(), ');
if (isset($tableColumn['length'])) {
$length = $tableColumn['length'];
$decimal = '';
} else {
$length = strtok('(), ');
$decimal = strtok('(), ') ? strtok('(), '):null;
}
$type = array();
$unsigned = $fixed = null;
if ( ! isset($tableColumn['name'])) {
$tableColumn['name'] = '';
}
$scale = null;
$precision = null;
$type = $this->_platform->getDoctrineTypeMapping($dbType);
switch ($dbType) {
case 'char':
$fixed = true;
break;
case 'float':
case 'double':
case 'real':
case 'numeric':
case 'decimal':
if(preg_match('([A-Za-z]+\(([0-9]+)\,([0-9]+)\))', $tableColumn['type'], $match)) {
$precision = $match[1];
$scale = $match[2];
$length = null;
}
break;
case 'tinyint':
case 'smallint':
case 'mediumint':
case 'int':
case 'integer':
case 'bigint':
case 'tinyblob':
case 'mediumblob':
case 'longblob':
case 'blob':
case 'binary':
case 'varbinary':
case 'year':
$length = null;
break;
}
$length = ((int) $length == 0) ? null : (int) $length;
$def = array(
'type' => $type,
'length' => $length,
'unsigned' => (bool) $unsigned,
'fixed' => (bool) $fixed
);
$options = array(
'length' => $length,
'unsigned' => (bool)$unsigned,
'fixed' => (bool)$fixed,
'default' => $tableColumn['default'],
'notnull' => (bool) ($tableColumn['null'] != 'YES'),
'scale' => null,
'precision' => null,
'autoincrement' => (bool) (strpos($tableColumn['extra'], 'auto_increment') !== false),
);
if ($scale !== null && $precision !== null) {
$options['scale'] = $scale;
$options['precision'] = $precision;
}
return new Column($tableColumn['field'], \Doctrine\DBAL\Types\Type::getType($type), $options);
}
public function _getPortableTableForeignKeyDefinition($tableForeignKey)
{
$tableForeignKey = array_change_key_case($tableForeignKey, CASE_LOWER);
if (!isset($tableForeignKey['delete_rule']) || $tableForeignKey['delete_rule'] == "RESTRICT") {
$tableForeignKey['delete_rule'] = null;
}
if (!isset($tableForeignKey['update_rule']) || $tableForeignKey['update_rule'] == "RESTRICT") {
$tableForeignKey['update_rule'] = null;
}
return new ForeignKeyConstraint(
(array)$tableForeignKey['column_name'],
$tableForeignKey['referenced_table_name'],
(array)$tableForeignKey['referenced_column_name'],
$tableForeignKey['constraint_name'],
array(
'onUpdate' => $tableForeignKey['update_rule'],
'onDelete' => $tableForeignKey['delete_rule'],
)
);
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* xxx
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @version $Revision$
* @since 2.0
*/
class PostgreSqlSchemaManager extends AbstractSchemaManager
{
protected function _getPortableTableForeignKeyDefinition($tableForeignKey)
{
$onUpdate = null;
$onDelete = null;
if (preg_match('(ON UPDATE ([a-zA-Z0-9]+))', $tableForeignKey['condef'], $match)) {
$onUpdate = $match[1];
}
if (preg_match('(ON DELETE ([a-zA-Z0-9]+))', $tableForeignKey['condef'], $match)) {
$onDelete = $match[1];
}
if (preg_match('/FOREIGN KEY \((.+)\) REFERENCES (.+)\((.+)\)/', $tableForeignKey['condef'], $values)) {
$localColumns = array_map('trim', explode(",", $values[1]));
$foreignColumns = array_map('trim', explode(",", $values[3]));
$foreignTable = $values[2];
}
return new ForeignKeyConstraint(
$localColumns, $foreignTable, $foreignColumns, $tableForeignKey['conname'],
array('onUpdate' => $onUpdate, 'onDelete' => $onDelete)
);
}
public function dropDatabase($database)
{
$params = $this->_conn->getParams();
$params["dbname"] = "postgres";
$tmpPlatform = $this->_platform;
$tmpConn = $this->_conn;
$this->_conn = \Doctrine\DBAL\DriverManager::getConnection($params);
$this->_platform = $this->_conn->getDatabasePlatform();
parent::dropDatabase($database);
$this->_platform = $tmpPlatform;
$this->_conn = $tmpConn;
}
public function createDatabase($database)
{
$params = $this->_conn->getParams();
$params["dbname"] = "postgres";
$tmpPlatform = $this->_platform;
$tmpConn = $this->_conn;
$this->_conn = \Doctrine\DBAL\DriverManager::getConnection($params);
$this->_platform = $this->_conn->getDatabasePlatform();
parent::createDatabase($database);
$this->_platform = $tmpPlatform;
$this->_conn = $tmpConn;
}
protected function _getPortableTriggerDefinition($trigger)
{
return $trigger['trigger_name'];
}
protected function _getPortableViewDefinition($view)
{
return new View($view['viewname'], $view['definition']);
}
protected function _getPortableUserDefinition($user)
{
return array(
'user' => $user['usename'],
'password' => $user['passwd']
);
}
protected function _getPortableTableDefinition($table)
{
return $table['table_name'];
}
/**
* @license New BSD License
* @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html
* @param array $tableIndexes
* @param string $tableName
* @return array
*/
protected function _getPortableTableIndexesList($tableIndexes, $tableName=null)
{
$buffer = array();
foreach ($tableIndexes AS $row) {
$colNumbers = explode(' ', $row['indkey']);
$colNumbersSql = 'IN (' . join(' ,', $colNumbers) . ' )';
$columnNameSql = "SELECT attnum, attname FROM pg_attribute
WHERE attrelid={$row['indrelid']} AND attnum $colNumbersSql ORDER BY attnum ASC;";
$stmt = $this->_conn->executeQuery($columnNameSql);
$indexColumns = $stmt->fetchAll();
// required for getting the order of the columns right.
foreach ($colNumbers AS $colNum) {
foreach ($indexColumns as $colRow) {
if ($colNum == $colRow['attnum']) {
$buffer[] = array(
'key_name' => $row['relname'],
'column_name' => trim($colRow['attname']),
'non_unique' => !$row['indisunique'],
'primary' => $row['indisprimary']
);
}
}
}
}
return parent::_getPortableTableIndexesList($buffer);
}
protected function _getPortableDatabaseDefinition($database)
{
return $database['datname'];
}
protected function _getPortableSequenceDefinition($sequence)
{
$data = $this->_conn->fetchAll('SELECT min_value, increment_by FROM ' . $sequence['relname']);
return new Sequence($sequence['relname'], $data[0]['increment_by'], $data[0]['min_value']);
}
protected function _getPortableTableColumnDefinition($tableColumn)
{
$tableColumn = array_change_key_case($tableColumn, CASE_LOWER);
if (strtolower($tableColumn['type']) === 'varchar') {
// get length from varchar definition
$length = preg_replace('~.*\(([0-9]*)\).*~', '$1', $tableColumn['complete_type']);
$tableColumn['length'] = $length;
}
$matches = array();
$autoincrement = false;
if (preg_match("/^nextval\('(.*)'(::.*)?\)$/", $tableColumn['default'], $matches)) {
$tableColumn['sequence'] = $matches[1];
$tableColumn['default'] = null;
$autoincrement = true;
}
if (stripos($tableColumn['default'], 'NULL') === 0) {
$tableColumn['default'] = null;
}
$length = (isset($tableColumn['length'])) ? $tableColumn['length'] : null;
if ($length == '-1' && isset($tableColumn['atttypmod'])) {
$length = $tableColumn['atttypmod'] - 4;
}
if ((int) $length <= 0) {
$length = null;
}
$type = array();
$fixed = null;
if (!isset($tableColumn['name'])) {
$tableColumn['name'] = '';
}
$precision = null;
$scale = null;
if ($this->_platform->hasDoctrineTypeMappingFor($tableColumn['type'])) {
$dbType = strtolower($tableColumn['type']);
} else {
$dbType = strtolower($tableColumn['domain_type']);
$tableColumn['complete_type'] = $tableColumn['domain_complete_type'];
}
$type = $this->_platform->getDoctrineTypeMapping($dbType);
switch ($dbType) {
case 'smallint':
case 'int2':
$length = null;
break;
case 'int':
case 'int4':
case 'integer':
$length = null;
break;
case 'bigint':
case 'int8':
$length = null;
break;
case 'bool':
case 'boolean':
$length = null;
break;
case 'text':
$fixed = false;
break;
case 'varchar':
case 'interval':
case '_varchar':
$fixed = false;
break;
case 'char':
case 'bpchar':
$fixed = true;
break;
case 'float':
case 'float4':
case 'float8':
case 'double':
case 'double precision':
case 'real':
case 'decimal':
case 'money':
case 'numeric':
if (preg_match('([A-Za-z]+\(([0-9]+)\,([0-9]+)\))', $tableColumn['complete_type'], $match)) {
$precision = $match[1];
$scale = $match[2];
$length = null;
}
break;
case 'year':
$length = null;
break;
}
$options = array(
'length' => $length,
'notnull' => (bool) $tableColumn['isnotnull'],
'default' => $tableColumn['default'],
'primary' => (bool) ($tableColumn['pri'] == 't'),
'precision' => $precision,
'scale' => $scale,
'fixed' => $fixed,
'unsigned' => false,
'autoincrement' => $autoincrement,
);
return new Column($tableColumn['field'], \Doctrine\DBAL\Types\Type::getType($type), $options);
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* Representation of a Database View
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 1.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class View extends AbstractAsset
{
/**
* @var string
*/
private $_sql;
public function __construct($name, $sql)
{
$this->_setName($name);
$this->_sql = $sql;
}
/**
* @return string
*/
public function getSql()
{
return $this->_sql;
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* IBM Db2 Schema Manager
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 1.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class DB2SchemaManager extends AbstractSchemaManager
{
/**
* Return a list of all tables in the current database
*
* Apparently creator is the schema not the user who created it:
* {@link http://publib.boulder.ibm.com/infocenter/dzichelp/v2r2/index.jsp?topic=/com.ibm.db29.doc.sqlref/db2z_sysibmsystablestable.htm}
*
* @return array
*/
public function listTableNames()
{
$sql = $this->_platform->getListTablesSQL();
$sql .= " AND CREATOR = UPPER('".$this->_conn->getUsername()."')";
$tables = $this->_conn->fetchAll($sql);
return $this->_getPortableTablesList($tables);
}
/**
* Get Table Column Definition
*
* @param array $tableColumn
* @return Column
*/
protected function _getPortableTableColumnDefinition($tableColumn)
{
$tableColumn = array_change_key_case($tableColumn, \CASE_LOWER);
$length = null;
$fixed = null;
$unsigned = false;
$scale = false;
$precision = false;
$type = $this->_platform->getDoctrineTypeMapping($tableColumn['typename']);
switch (strtolower($tableColumn['typename'])) {
case 'varchar':
$length = $tableColumn['length'];
$fixed = false;
break;
case 'character':
$length = $tableColumn['length'];
$fixed = true;
break;
case 'clob':
$length = $tableColumn['length'];
break;
case 'decimal':
case 'double':
case 'real':
$scale = $tableColumn['scale'];
$precision = $tableColumn['length'];
break;
}
$options = array(
'length' => $length,
'unsigned' => (bool)$unsigned,
'fixed' => (bool)$fixed,
'default' => ($tableColumn['default'] == "NULL") ? null : $tableColumn['default'],
'notnull' => (bool) ($tableColumn['nulls'] == 'N'),
'scale' => null,
'precision' => null,
'platformOptions' => array(),
);
if ($scale !== null && $precision !== null) {
$options['scale'] = $scale;
$options['precision'] = $precision;
}
return new Column($tableColumn['colname'], \Doctrine\DBAL\Types\Type::getType($type), $options);
}
protected function _getPortableTablesList($tables)
{
$tableNames = array();
foreach ($tables AS $tableRow) {
$tableRow = array_change_key_case($tableRow, \CASE_LOWER);
$tableNames[] = $tableRow['name'];
}
return $tableNames;
}
protected function _getPortableTableIndexesList($tableIndexes, $tableName=null)
{
$tableIndexRows = array();
$indexes = array();
foreach($tableIndexes AS $indexKey => $data) {
$data = array_change_key_case($data, \CASE_LOWER);
$unique = ($data['uniquerule'] == "D") ? false : true;
$primary = ($data['uniquerule'] == "P");
$indexName = strtolower($data['name']);
if ($primary) {
$keyName = 'primary';
} else {
$keyName = $indexName;
}
$indexes[$keyName] = new Index($indexName, explode("+", ltrim($data['colnames'], '+')), $unique, $primary);
}
return $indexes;
}
protected function _getPortableTableForeignKeyDefinition($tableForeignKey)
{
$tableForeignKey = array_change_key_case($tableForeignKey, CASE_LOWER);
$tableForeignKey['deleterule'] = $this->_getPortableForeignKeyRuleDef($tableForeignKey['deleterule']);
$tableForeignKey['updaterule'] = $this->_getPortableForeignKeyRuleDef($tableForeignKey['updaterule']);
return new ForeignKeyConstraint(
array_map('trim', (array)$tableForeignKey['fkcolnames']),
$tableForeignKey['reftbname'],
array_map('trim', (array)$tableForeignKey['pkcolnames']),
$tableForeignKey['relname'],
array(
'onUpdate' => $tableForeignKey['updaterule'],
'onDelete' => $tableForeignKey['deleterule'],
)
);
}
protected function _getPortableForeignKeyRuleDef($def)
{
if ($def == "C") {
return "CASCADE";
} else if ($def == "N") {
return "SET NULL";
}
return null;
}
protected function _getPortableViewDefinition($view)
{
$view = array_change_key_case($view, \CASE_LOWER);
// sadly this still segfaults on PDO_IBM, see http://pecl.php.net/bugs/bug.php?id=17199
//$view['text'] = (is_resource($view['text']) ? stream_get_contents($view['text']) : $view['text']);
if (!is_resource($view['text'])) {
$pos = strpos($view['text'], ' AS ');
$sql = substr($view['text'], $pos+4);
} else {
$sql = '';
}
return new View($view['name'], $sql);
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* SqliteSchemaManager
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Jonathan H. Wage <jonwage@gmail.com>
* @version $Revision$
* @since 2.0
*/
class SqliteSchemaManager extends AbstractSchemaManager
{
/**
* {@inheritdoc}
*
* @override
*/
public function dropDatabase($database)
{
if (file_exists($database)) {
unlink($database);
}
}
/**
* {@inheritdoc}
*
* @override
*/
public function createDatabase($database)
{
$params = $this->_conn->getParams();
$driver = $params['driver'];
$options = array(
'driver' => $driver,
'path' => $database
);
$conn = \Doctrine\DBAL\DriverManager::getConnection($options);
$conn->connect();
$conn->close();
}
protected function _getPortableTableDefinition($table)
{
return $table['name'];
}
/**
* @license New BSD License
* @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html
* @param array $tableIndexes
* @param string $tableName
* @return array
*/
protected function _getPortableTableIndexesList($tableIndexes, $tableName=null)
{
$indexBuffer = array();
// fetch primary
$stmt = $this->_conn->executeQuery( "PRAGMA TABLE_INFO ('$tableName')" );
$indexArray = $stmt->fetchAll(\PDO::FETCH_ASSOC);
foreach($indexArray AS $indexColumnRow) {
if($indexColumnRow['pk'] == "1") {
$indexBuffer[] = array(
'key_name' => 'primary',
'primary' => true,
'non_unique' => false,
'column_name' => $indexColumnRow['name']
);
}
}
// fetch regular indexes
foreach($tableIndexes AS $tableIndex) {
$keyName = $tableIndex['name'];
$idx = array();
$idx['key_name'] = $keyName;
$idx['primary'] = false;
$idx['non_unique'] = $tableIndex['unique']?false:true;
$stmt = $this->_conn->executeQuery( "PRAGMA INDEX_INFO ( '{$keyName}' )" );
$indexArray = $stmt->fetchAll(\PDO::FETCH_ASSOC);
foreach ( $indexArray as $indexColumnRow ) {
$idx['column_name'] = $indexColumnRow['name'];
$indexBuffer[] = $idx;
}
}
return parent::_getPortableTableIndexesList($indexBuffer, $tableName);
}
protected function _getPortableTableIndexDefinition($tableIndex)
{
return array(
'name' => $tableIndex['name'],
'unique' => (bool) $tableIndex['unique']
);
}
protected function _getPortableTableColumnDefinition($tableColumn)
{
$e = explode('(', $tableColumn['type']);
$tableColumn['type'] = $e[0];
if (isset($e[1])) {
$length = trim($e[1], ')');
$tableColumn['length'] = $length;
}
$dbType = strtolower($tableColumn['type']);
$length = isset($tableColumn['length']) ? $tableColumn['length'] : null;
$unsigned = (boolean) isset($tableColumn['unsigned']) ? $tableColumn['unsigned'] : false;
$fixed = false;
$type = $this->_platform->getDoctrineTypeMapping($dbType);
$default = $tableColumn['dflt_value'];
if ($default == 'NULL') {
$default = null;
}
$notnull = (bool) $tableColumn['notnull'];
if ( ! isset($tableColumn['name'])) {
$tableColumn['name'] = '';
}
$precision = null;
$scale = null;
switch ($dbType) {
case 'char':
$fixed = true;
break;
case 'float':
case 'double':
case 'real':
case 'decimal':
case 'numeric':
list($precision, $scale) = array_map('trim', explode(', ', $tableColumn['length']));
$length = null;
break;
}
$options = array(
'length' => $length,
'unsigned' => (bool) $unsigned,
'fixed' => $fixed,
'notnull' => $notnull,
'default' => $default,
'precision' => $precision,
'scale' => $scale,
'autoincrement' => (bool) $tableColumn['pk'],
);
return new Column($tableColumn['name'], \Doctrine\DBAL\Types\Type::getType($type), $options);
}
protected function _getPortableViewDefinition($view)
{
return new View($view['name'], $view['sql']);
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* Compare to Schemas and return an instance of SchemaDiff
*
* @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
* @license http://ez.no/licenses/new_bsd New BSD License
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class Comparator
{
/**
* @param Schema $fromSchema
* @param Schema $toSchema
* @return SchemaDiff
*/
static public function compareSchemas( Schema $fromSchema, Schema $toSchema )
{
$c = new self();
return $c->compare($fromSchema, $toSchema);
}
/**
* Returns a SchemaDiff object containing the differences between the schemas $fromSchema and $toSchema.
*
* The returned diferences are returned in such a way that they contain the
* operations to change the schema stored in $fromSchema to the schema that is
* stored in $toSchema.
*
* @param Schema $fromSchema
* @param Schema $toSchema
*
* @return SchemaDiff
*/
public function compare(Schema $fromSchema, Schema $toSchema)
{
$diff = new SchemaDiff();
$foreignKeysToTable = array();
foreach ( $toSchema->getTables() AS $tableName => $table ) {
if ( !$fromSchema->hasTable($tableName) ) {
$diff->newTables[$tableName] = $table;
} else {
$tableDifferences = $this->diffTable( $fromSchema->getTable($tableName), $table );
if ( $tableDifferences !== false ) {
$diff->changedTables[$tableName] = $tableDifferences;
}
}
}
/* Check if there are tables removed */
foreach ( $fromSchema->getTables() AS $tableName => $table ) {
if ( !$toSchema->hasTable($tableName) ) {
$diff->removedTables[$tableName] = $table;
}
// also remember all foreign keys that point to a specific table
foreach ($table->getForeignKeys() AS $foreignKey) {
$foreignTable = strtolower($foreignKey->getForeignTableName());
if (!isset($foreignKeysToTable[$foreignTable])) {
$foreignKeysToTable[$foreignTable] = array();
}
$foreignKeysToTable[$foreignTable][] = $foreignKey;
}
}
foreach ($diff->removedTables AS $tableName => $table) {
if (isset($foreignKeysToTable[$tableName])) {
$diff->orphanedForeignKeys = array_merge($diff->orphanedForeignKeys, $foreignKeysToTable[$tableName]);
}
}
foreach ( $toSchema->getSequences() AS $sequenceName => $sequence) {
if (!$fromSchema->hasSequence($sequenceName)) {
$diff->newSequences[] = $sequence;
} else {
if ($this->diffSequence($sequence, $fromSchema->getSequence($sequenceName))) {
$diff->changedSequences[] = $fromSchema->getSequence($sequenceName);
}
}
}
foreach ($fromSchema->getSequences() AS $sequenceName => $sequence) {
if (!$toSchema->hasSequence($sequenceName)) {
$diff->removedSequences[] = $sequence;
}
}
return $diff;
}
/**
*
* @param Sequence $sequence1
* @param Sequence $sequence2
*/
public function diffSequence(Sequence $sequence1, Sequence $sequence2)
{
if($sequence1->getAllocationSize() != $sequence2->getAllocationSize()) {
return true;
}
if($sequence1->getInitialValue() != $sequence2->getInitialValue()) {
return true;
}
return false;
}
/**
* Returns the difference between the tables $table1 and $table2.
*
* If there are no differences this method returns the boolean false.
*
* @param Table $table1
* @param Table $table2
*
* @return bool|TableDiff
*/
public function diffTable(Table $table1, Table $table2)
{
$changes = 0;
$tableDifferences = new TableDiff($table1->getName());
$table1Columns = $table1->getColumns();
$table2Columns = $table2->getColumns();
/* See if all the fields in table 1 exist in table 2 */
foreach ( $table2Columns as $columnName => $column ) {
if ( !$table1->hasColumn($columnName) ) {
$tableDifferences->addedColumns[$columnName] = $column;
$changes++;
}
}
/* See if there are any removed fields in table 2 */
foreach ( $table1Columns as $columnName => $column ) {
if ( !$table2->hasColumn($columnName) ) {
$tableDifferences->removedColumns[$columnName] = $column;
$changes++;
}
}
foreach ( $table1Columns as $columnName => $column ) {
if ( $table2->hasColumn($columnName) ) {
$changedProperties = $this->diffColumn( $column, $table2->getColumn($columnName) );
if (count($changedProperties) ) {
$columnDiff = new ColumnDiff($column->getName(), $table2->getColumn($columnName), $changedProperties);
$tableDifferences->changedColumns[$column->getName()] = $columnDiff;
$changes++;
}
}
}
$this->detectColumnRenamings($tableDifferences);
$table1Indexes = $table1->getIndexes();
$table2Indexes = $table2->getIndexes();
foreach ($table2Indexes AS $index2Name => $index2Definition) {
foreach ($table1Indexes AS $index1Name => $index1Definition) {
if ($this->diffIndex($index1Definition, $index2Definition) === false) {
unset($table1Indexes[$index1Name]);
unset($table2Indexes[$index2Name]);
} else {
if ($index1Name == $index2Name) {
$tableDifferences->changedIndexes[$index2Name] = $table2Indexes[$index2Name];
unset($table1Indexes[$index1Name]);
unset($table2Indexes[$index2Name]);
$changes++;
}
}
}
}
foreach ($table1Indexes AS $index1Name => $index1Definition) {
$tableDifferences->removedIndexes[$index1Name] = $index1Definition;
$changes++;
}
foreach ($table2Indexes AS $index2Name => $index2Definition) {
$tableDifferences->addedIndexes[$index2Name] = $index2Definition;
$changes++;
}
$fromFkeys = $table1->getForeignKeys();
$toFkeys = $table2->getForeignKeys();
foreach ($fromFkeys AS $key1 => $constraint1) {
foreach ($toFkeys AS $key2 => $constraint2) {
if($this->diffForeignKey($constraint1, $constraint2) === false) {
unset($fromFkeys[$key1]);
unset($toFkeys[$key2]);
} else {
if (strtolower($constraint1->getName()) == strtolower($constraint2->getName())) {
$tableDifferences->changedForeignKeys[] = $constraint2;
$changes++;
unset($fromFkeys[$key1]);
unset($toFkeys[$key2]);
}
}
}
}
foreach ($fromFkeys AS $key1 => $constraint1) {
$tableDifferences->removedForeignKeys[] = $constraint1;
$changes++;
}
foreach ($toFkeys AS $key2 => $constraint2) {
$tableDifferences->addedForeignKeys[] = $constraint2;
$changes++;
}
return $changes ? $tableDifferences : false;
}
/**
* Try to find columns that only changed their name, rename operations maybe cheaper than add/drop
* however ambiguouties between different possibilites should not lead to renaming at all.
*
* @param TableDiff $tableDifferences
*/
private function detectColumnRenamings(TableDiff $tableDifferences)
{
$renameCandidates = array();
foreach ($tableDifferences->addedColumns AS $addedColumnName => $addedColumn) {
foreach ($tableDifferences->removedColumns AS $removedColumnName => $removedColumn) {
if (count($this->diffColumn($addedColumn, $removedColumn)) == 0) {
$renameCandidates[$addedColumn->getName()][] = array($removedColumn, $addedColumn);
}
}
}
foreach ($renameCandidates AS $candidate => $candidateColumns) {
if (count($candidateColumns) == 1) {
list($removedColumn, $addedColumn) = $candidateColumns[0];
$tableDifferences->renamedColumns[$removedColumn->getName()] = $addedColumn;
unset($tableDifferences->addedColumns[$addedColumnName]);
unset($tableDifferences->removedColumns[$removedColumnName]);
}
}
}
/**
* @param ForeignKeyConstraint $key1
* @param ForeignKeyConstraint $key2
* @return bool
*/
public function diffForeignKey(ForeignKeyConstraint $key1, ForeignKeyConstraint $key2)
{
if (array_map('strtolower', $key1->getLocalColumns()) != array_map('strtolower', $key2->getLocalColumns())) {
return true;
}
if (array_map('strtolower', $key1->getForeignColumns()) != array_map('strtolower', $key2->getForeignColumns())) {
return true;
}
if ($key1->onUpdate() != $key2->onUpdate()) {
return true;
}
if ($key1->onDelete() != $key2->onDelete()) {
return true;
}
return false;
}
/**
* Returns the difference between the fields $field1 and $field2.
*
* If there are differences this method returns $field2, otherwise the
* boolean false.
*
* @param Column $column1
* @param Column $column2
*
* @return array
*/
public function diffColumn(Column $column1, Column $column2)
{
$changedProperties = array();
if ( $column1->getType() != $column2->getType() ) {
$changedProperties[] = 'type';
}
if ($column1->getNotnull() != $column2->getNotnull()) {
$changedProperties[] = 'notnull';
}
if ($column1->getDefault() != $column2->getDefault()) {
$changedProperties[] = 'default';
}
if ($column1->getUnsigned() != $column2->getUnsigned()) {
$changedProperties[] = 'unsigned';
}
if ($column1->getType() instanceof \Doctrine\DBAL\Types\StringType) {
if ($column1->getLength() != $column2->getLength()) {
$changedProperties[] = 'length';
}
if ($column1->getFixed() != $column2->getFixed()) {
$changedProperties[] = 'fixed';
}
}
if ($column1->getType() instanceof \Doctrine\DBAL\Types\DecimalType) {
if ($column1->getPrecision() != $column2->getPrecision()) {
$changedProperties[] = 'precision';
}
if ($column1->getScale() != $column2->getScale()) {
$changedProperties[] = 'scale';
}
}
if ($column1->getAutoincrement() != $column2->getAutoincrement()) {
$changedProperties[] = 'autoincrement';
}
return $changedProperties;
}
/**
* Finds the difference between the indexes $index1 and $index2.
*
* Compares $index1 with $index2 and returns $index2 if there are any
* differences or false in case there are no differences.
*
* @param Index $index1
* @param Index $index2
* @return bool
*/
public function diffIndex(Index $index1, Index $index2)
{
if ($index1->isFullfilledBy($index2) && $index2->isFullfilledBy($index1)) {
return false;
}
return true;
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Schema\Visitor\Visitor;
class Index extends AbstractAsset implements Constraint
{
/**
* @var array
*/
protected $_columns;
/**
* @var bool
*/
protected $_isUnique = false;
/**
* @var bool
*/
protected $_isPrimary = false;
/**
* @param string $indexName
* @param array $column
* @param bool $isUnique
* @param bool $isPrimary
*/
public function __construct($indexName, array $columns, $isUnique=false, $isPrimary=false)
{
$isUnique = ($isPrimary)?true:$isUnique;
$this->_setName($indexName);
$this->_isUnique = $isUnique;
$this->_isPrimary = $isPrimary;
foreach($columns AS $column) {
$this->_addColumn($column);
}
}
/**
* @param string $column
*/
protected function _addColumn($column)
{
if(is_string($column)) {
$this->_columns[] = strtolower($column);
} else {
throw new \InvalidArgumentException("Expecting a string as Index Column");
}
}
/**
* @return array
*/
public function getColumns()
{
return $this->_columns;
}
/**
* @return bool
*/
public function isUnique()
{
return $this->_isUnique;
}
/**
* @return bool
*/
public function isPrimary()
{
return $this->_isPrimary;
}
/**
* @param string $columnName
* @param int $pos
* @return bool
*/
public function hasColumnAtPosition($columnName, $pos=0)
{
$columnName = strtolower($columnName);
$indexColumns = \array_map('strtolower', $this->getColumns());
return \array_search($columnName, $indexColumns) === $pos;
}
/**
* Check if this index exactly spans the given column names in the correct order.
*
* @param array $columnNames
* @return boolean
*/
public function spansColumns(array $columnNames)
{
$sameColumns = true;
for ($i = 0; $i < count($this->_columns); $i++) {
if (!isset($columnNames[$i]) || strtolower($this->_columns[$i]) != strtolower($columnNames[$i])) {
$sameColumns = false;
}
}
return $sameColumns;
}
/**
* Check if the other index already fullfills all the indexing and constraint needs of the current one.
*
* @param Index $other
* @return bool
*/
public function isFullfilledBy(Index $other)
{
// allow the other index to be equally large only. It being larger is an option
// but it creates a problem with scenarios of the kind PRIMARY KEY(foo,bar) UNIQUE(foo)
if (count($other->getColumns()) != count($this->getColumns())) {
return false;
}
// Check if columns are the same, and even in the same order
$sameColumns = $this->spansColumns($other->getColumns());
if ($sameColumns) {
if (!$this->isUnique() && !$this->isPrimary()) {
// this is a special case: If the current key is neither primary or unique, any uniqe or
// primary key will always have the same effect for the index and there cannot be any constraint
// overlaps. This means a primary or unique index can always fullfill the requirements of just an
// index that has no constraints.
return true;
} else if ($other->isPrimary() != $this->isPrimary()) {
return false;
} else if ($other->isUnique() != $this->isUnique()) {
return false;
}
return true;
}
return false;
}
/**
* Detect if the other index is a non-unique, non primary index that can be overwritten by this one.
*
* @param Index $other
* @return bool
*/
public function overrules(Index $other)
{
if ($other->isPrimary() || $other->isUnique()) {
return false;
}
if ($this->spansColumns($other->getColumns()) && ($this->isPrimary() || $this->isUnique())) {
return true;
}
return false;
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Types;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* Base class for schema managers. Schema managers are used to inspect and/or
* modify the database schema/structure.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Roman Borschel <roman@code-factory.org>
* @author Jonathan H. Wage <jonwage@gmail.com>
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @version $Revision$
* @since 2.0
*/
abstract class AbstractSchemaManager
{
/**
* Holds instance of the Doctrine connection for this schema manager
*
* @var \Doctrine\DBAL\Connection
*/
protected $_conn;
/**
* Holds instance of the database platform used for this schema manager
*
* @var \Doctrine\DBAL\Platforms\AbstractPlatform
*/
protected $_platform;
/**
* Constructor. Accepts the Connection instance to manage the schema for
*
* @param \Doctrine\DBAL\Connection $conn
*/
public function __construct(\Doctrine\DBAL\Connection $conn)
{
$this->_conn = $conn;
$this->_platform = $this->_conn->getDatabasePlatform();
}
/**
* Return associated platform.
*
* @return \Doctrine\DBAL\Platform\AbstractPlatform
*/
public function getDatabasePlatform()
{
return $this->_platform;
}
/**
* Try any method on the schema manager. Normally a method throws an
* exception when your DBMS doesn't support it or if an error occurs.
* This method allows you to try and method on your SchemaManager
* instance and will return false if it does not work or is not supported.
*
* <code>
* $result = $sm->tryMethod('dropView', 'view_name');
* </code>
*
* @return mixed
*/
public function tryMethod()
{
$args = func_get_args();
$method = $args[0];
unset($args[0]);
$args = array_values($args);
try {
return call_user_func_array(array($this, $method), $args);
} catch (\Exception $e) {
return false;
}
}
/**
* List the available databases for this connection
*
* @return array $databases
*/
public function listDatabases()
{
$sql = $this->_platform->getListDatabasesSQL();
$databases = $this->_conn->fetchAll($sql);
return $this->_getPortableDatabasesList($databases);
}
/**
* List the available sequences for this connection
*
* @return Sequence[]
*/
public function listSequences($database = null)
{
if (is_null($database)) {
$database = $this->_conn->getDatabase();
}
$sql = $this->_platform->getListSequencesSQL($database);
$sequences = $this->_conn->fetchAll($sql);
return $this->_getPortableSequencesList($sequences);
}
/**
* List the columns for a given table.
*
* In contrast to other libraries and to the old version of Doctrine,
* this column definition does try to contain the 'primary' field for
* the reason that it is not portable accross different RDBMS. Use
* {@see listTableIndexes($tableName)} to retrieve the primary key
* of a table. We're a RDBMS specifies more details these are held
* in the platformDetails array.
*
* @param string $table The name of the table.
* @return Column[]
*/
public function listTableColumns($table)
{
$sql = $this->_platform->getListTableColumnsSQL($table);
$tableColumns = $this->_conn->fetchAll($sql);
return $this->_getPortableTableColumnList($tableColumns);
}
/**
* List the indexes for a given table returning an array of Index instances.
*
* Keys of the portable indexes list are all lower-cased.
*
* @param string $table The name of the table
* @return Index[] $tableIndexes
*/
public function listTableIndexes($table)
{
$sql = $this->_platform->getListTableIndexesSQL($table);
$tableIndexes = $this->_conn->fetchAll($sql);
return $this->_getPortableTableIndexesList($tableIndexes, $table);
}
/**
* Return true if all the given tables exist.
*
* @param array $tableNames
* @return bool
*/
public function tablesExist($tableNames)
{
$tableNames = array_map('strtolower', (array)$tableNames);
return count($tableNames) == count(\array_intersect($tableNames, array_map('strtolower', $this->listTableNames())));
}
/**
* Return a list of all tables in the current database
*
* @return array
*/
public function listTableNames()
{
$sql = $this->_platform->getListTablesSQL();
$tables = $this->_conn->fetchAll($sql);
return $this->_getPortableTablesList($tables);
}
/**
* List the tables for this connection
*
* @return Table[]
*/
public function listTables()
{
$tableNames = $this->listTableNames();
$tables = array();
foreach ($tableNames AS $tableName) {
$tables[] = $this->listTableDetails($tableName);
}
return $tables;
}
/**
* @param string $tableName
* @return Table
*/
public function listTableDetails($tableName)
{
$columns = $this->listTableColumns($tableName);
$foreignKeys = array();
if ($this->_platform->supportsForeignKeyConstraints()) {
$foreignKeys = $this->listTableForeignKeys($tableName);
}
$indexes = $this->listTableIndexes($tableName);
return new Table($tableName, $columns, $indexes, $foreignKeys, false, array());
}
/**
* List the views this connection has
*
* @return View[]
*/
public function listViews()
{
$database = $this->_conn->getDatabase();
$sql = $this->_platform->getListViewsSQL($database);
$views = $this->_conn->fetchAll($sql);
return $this->_getPortableViewsList($views);
}
/**
* List the foreign keys for the given table
*
* @param string $table The name of the table
* @return ForeignKeyConstraint[]
*/
public function listTableForeignKeys($table, $database = null)
{
if (is_null($database)) {
$database = $this->_conn->getDatabase();
}
$sql = $this->_platform->getListTableForeignKeysSQL($table, $database);
$tableForeignKeys = $this->_conn->fetchAll($sql);
return $this->_getPortableTableForeignKeysList($tableForeignKeys);
}
/* drop*() Methods */
/**
* Drops a database.
*
* NOTE: You can not drop the database this SchemaManager is currently connected to.
*
* @param string $database The name of the database to drop
*/
public function dropDatabase($database)
{
$this->_execSql($this->_platform->getDropDatabaseSQL($database));
}
/**
* Drop the given table
*
* @param string $table The name of the table to drop
*/
public function dropTable($table)
{
$this->_execSql($this->_platform->getDropTableSQL($table));
}
/**
* Drop the index from the given table
*
* @param Index|string $index The name of the index
* @param string|Table $table The name of the table
*/
public function dropIndex($index, $table)
{
if($index instanceof Index) {
$index = $index->getName();
}
$this->_execSql($this->_platform->getDropIndexSQL($index, $table));
}
/**
* Drop the constraint from the given table
*
* @param Constraint $constraint
* @param string $table The name of the table
*/
public function dropConstraint(Constraint $constraint, $table)
{
$this->_execSql($this->_platform->getDropConstraintSQL($constraint, $table));
}
/**
* Drops a foreign key from a table.
*
* @param ForeignKeyConstraint|string $table The name of the table with the foreign key.
* @param Table|string $name The name of the foreign key.
* @return boolean $result
*/
public function dropForeignKey($foreignKey, $table)
{
$this->_execSql($this->_platform->getDropForeignKeySQL($foreignKey, $table));
}
/**
* Drops a sequence with a given name.
*
* @param string $name The name of the sequence to drop.
*/
public function dropSequence($name)
{
$this->_execSql($this->_platform->getDropSequenceSQL($name));
}
/**
* Drop a view
*
* @param string $name The name of the view
* @return boolean $result
*/
public function dropView($name)
{
$this->_execSql($this->_platform->getDropViewSQL($name));
}
/* create*() Methods */
/**
* Creates a new database.
*
* @param string $database The name of the database to create.
*/
public function createDatabase($database)
{
$this->_execSql($this->_platform->getCreateDatabaseSQL($database));
}
/**
* Create a new table.
*
* @param Table $table
* @param int $createFlags
*/
public function createTable(Table $table)
{
$createFlags = AbstractPlatform::CREATE_INDEXES|AbstractPlatform::CREATE_FOREIGNKEYS;
$this->_execSql($this->_platform->getCreateTableSQL($table, $createFlags));
}
/**
* Create a new sequence
*
* @param Sequence $sequence
* @throws Doctrine\DBAL\ConnectionException if something fails at database level
*/
public function createSequence($sequence)
{
$this->_execSql($this->_platform->getCreateSequenceSQL($sequence));
}
/**
* Create a constraint on a table
*
* @param Constraint $constraint
* @param string|Table $table
*/
public function createConstraint(Constraint $constraint, $table)
{
$this->_execSql($this->_platform->getCreateConstraintSQL($constraint, $table));
}
/**
* Create a new index on a table
*
* @param Index $index
* @param string $table name of the table on which the index is to be created
*/
public function createIndex(Index $index, $table)
{
$this->_execSql($this->_platform->getCreateIndexSQL($index, $table));
}
/**
* Create a new foreign key
*
* @param ForeignKeyConstraint $foreignKey ForeignKey instance
* @param string|Table $table name of the table on which the foreign key is to be created
*/
public function createForeignKey(ForeignKeyConstraint $foreignKey, $table)
{
$this->_execSql($this->_platform->getCreateForeignKeySQL($foreignKey, $table));
}
/**
* Create a new view
*
* @param View $view
*/
public function createView(View $view)
{
$this->_execSql($this->_platform->getCreateViewSQL($view->getName(), $view->getSql()));
}
/* dropAndCreate*() Methods */
/**
* Drop and create a constraint
*
* @param Constraint $constraint
* @param string $table
* @see dropConstraint()
* @see createConstraint()
*/
public function dropAndCreateConstraint(Constraint $constraint, $table)
{
$this->tryMethod('dropConstraint', $constraint, $table);
$this->createConstraint($constraint, $table);
}
/**
* Drop and create a new index on a table
*
* @param string|Table $table name of the table on which the index is to be created
* @param Index $index
*/
public function dropAndCreateIndex(Index $index, $table)
{
$this->tryMethod('dropIndex', $index->getName(), $table);
$this->createIndex($index, $table);
}
/**
* Drop and create a new foreign key
*
* @param ForeignKeyConstraint $foreignKey associative array that defines properties of the foreign key to be created.
* @param string|Table $table name of the table on which the foreign key is to be created
*/
public function dropAndCreateForeignKey(ForeignKeyConstraint $foreignKey, $table)
{
$this->tryMethod('dropForeignKey', $foreignKey, $table);
$this->createForeignKey($foreignKey, $table);
}
/**
* Drop and create a new sequence
*
* @param Sequence $sequence
* @throws Doctrine\DBAL\ConnectionException if something fails at database level
*/
public function dropAndCreateSequence(Sequence $sequence)
{
$this->tryMethod('createSequence', $seqName, $start, $allocationSize);
$this->createSequence($seqName, $start, $allocationSize);
}
/**
* Drop and create a new table.
*
* @param Table $table
*/
public function dropAndCreateTable(Table $table)
{
$this->tryMethod('dropTable', $table->getName());
$this->createTable($table);
}
/**
* Drop and creates a new database.
*
* @param string $database The name of the database to create.
*/
public function dropAndCreateDatabase($database)
{
$this->tryMethod('dropDatabase', $database);
$this->createDatabase($database);
}
/**
* Drop and create a new view
*
* @param View $view
*/
public function dropAndCreateView(View $view)
{
$this->tryMethod('dropView', $view->getName());
$this->createView($view);
}
/* alterTable() Methods */
/**
* Alter an existing tables schema
*
* @param TableDiff $tableDiff
*/
public function alterTable(TableDiff $tableDiff)
{
$queries = $this->_platform->getAlterTableSQL($tableDiff);
if (is_array($queries) && count($queries)) {
foreach ($queries AS $ddlQuery) {
$this->_execSql($ddlQuery);
}
}
}
/**
* Rename a given table to another name
*
* @param string $name The current name of the table
* @param string $newName The new name of the table
*/
public function renameTable($name, $newName)
{
$tableDiff = new TableDiff($name);
$tableDiff->newName = $newName;
$this->alterTable($tableDiff);
}
/**
* Methods for filtering return values of list*() methods to convert
* the native DBMS data definition to a portable Doctrine definition
*/
protected function _getPortableDatabasesList($databases)
{
$list = array();
foreach ($databases as $key => $value) {
if ($value = $this->_getPortableDatabaseDefinition($value)) {
$list[] = $value;
}
}
return $list;
}
protected function _getPortableDatabaseDefinition($database)
{
return $database;
}
protected function _getPortableFunctionsList($functions)
{
$list = array();
foreach ($functions as $key => $value) {
if ($value = $this->_getPortableFunctionDefinition($value)) {
$list[] = $value;
}
}
return $list;
}
protected function _getPortableFunctionDefinition($function)
{
return $function;
}
protected function _getPortableTriggersList($triggers)
{
$list = array();
foreach ($triggers as $key => $value) {
if ($value = $this->_getPortableTriggerDefinition($value)) {
$list[] = $value;
}
}
return $list;
}
protected function _getPortableTriggerDefinition($trigger)
{
return $trigger;
}
protected function _getPortableSequencesList($sequences)
{
$list = array();
foreach ($sequences as $key => $value) {
if ($value = $this->_getPortableSequenceDefinition($value)) {
$list[] = $value;
}
}
return $list;
}
/**
* @param array $sequence
* @return Sequence
*/
protected function _getPortableSequenceDefinition($sequence)
{
throw DBALException::notSupported('Sequences');
}
/**
* Independent of the database the keys of the column list result are lowercased.
*
* The name of the created column instance however is kept in its case.
*
* @param array $tableColumns
* @return array
*/
protected function _getPortableTableColumnList($tableColumns)
{
$list = array();
foreach ($tableColumns as $key => $column) {
if ($column = $this->_getPortableTableColumnDefinition($column)) {
$name = strtolower($column->getName());
$list[$name] = $column;
}
}
return $list;
}
/**
* Get Table Column Definition
*
* @param array $tableColumn
* @return Column
*/
abstract protected function _getPortableTableColumnDefinition($tableColumn);
/**
* Aggregate and group the index results according to the required data result.
*
* @param array $tableIndexRows
* @param string $tableName
* @return array
*/
protected function _getPortableTableIndexesList($tableIndexRows, $tableName=null)
{
$result = array();
foreach($tableIndexRows AS $tableIndex) {
$indexName = $keyName = $tableIndex['key_name'];
if($tableIndex['primary']) {
$keyName = 'primary';
}
$keyName = strtolower($keyName);
if(!isset($result[$keyName])) {
$result[$keyName] = array(
'name' => $indexName,
'columns' => array($tableIndex['column_name']),
'unique' => $tableIndex['non_unique'] ? false : true,
'primary' => $tableIndex['primary'],
);
} else {
$result[$keyName]['columns'][] = $tableIndex['column_name'];
}
}
$indexes = array();
foreach($result AS $indexKey => $data) {
$indexes[$indexKey] = new Index($data['name'], $data['columns'], $data['unique'], $data['primary']);
}
return $indexes;
}
protected function _getPortableTablesList($tables)
{
$list = array();
foreach ($tables as $key => $value) {
if ($value = $this->_getPortableTableDefinition($value)) {
$list[] = $value;
}
}
return $list;
}
protected function _getPortableTableDefinition($table)
{
return $table;
}
protected function _getPortableUsersList($users)
{
$list = array();
foreach ($users as $key => $value) {
if ($value = $this->_getPortableUserDefinition($value)) {
$list[] = $value;
}
}
return $list;
}
protected function _getPortableUserDefinition($user)
{
return $user;
}
protected function _getPortableViewsList($views)
{
$list = array();
foreach ($views as $key => $value) {
if ($view = $this->_getPortableViewDefinition($value)) {
$viewName = strtolower($view->getName());
$list[$viewName] = $view;
}
}
return $list;
}
protected function _getPortableViewDefinition($view)
{
return false;
}
protected function _getPortableTableForeignKeysList($tableForeignKeys)
{
$list = array();
foreach ($tableForeignKeys as $key => $value) {
if ($value = $this->_getPortableTableForeignKeyDefinition($value)) {
$list[] = $value;
}
}
return $list;
}
protected function _getPortableTableForeignKeyDefinition($tableForeignKey)
{
return $tableForeignKey;
}
protected function _execSql($sql)
{
foreach ((array) $sql as $query) {
$this->_conn->executeUpdate($query);
}
}
/**
* Create a schema instance for the current database.
*
* @return Schema
*/
public function createSchema()
{
$sequences = array();
if($this->_platform->supportsSequences()) {
$sequences = $this->listSequences();
}
$tables = $this->listTables();
return new Schema($tables, $sequences, $this->createSchemaConfig());
}
/**
* Create the configuration for this schema.
*
* @return SchemaConfig
*/
public function createSchemaConfig()
{
$schemaConfig = new SchemaConfig();
$schemaConfig->setMaxIdentifierLength($this->_platform->getMaxIdentifierLength());
return $schemaConfig;
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* The abstract asset allows to reset the name of all assets without publishing this to the public userland.
*
* This encapsulation hack is necessary to keep a consistent state of the database schema. Say we have a list of tables
* array($tableName => Table($tableName)); if you want to rename the table, you have to make sure
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
abstract class AbstractAsset
{
/**
* @var string
*/
protected $_name;
/**
* Set name of this asset
*
* @param string $name
*/
protected function _setName($name)
{
$this->_name = $name;
}
/**
* Return name of this schema asset.
*
* @return string
*/
public function getName()
{
return $this->_name;
}
/**
* Generate an identifier from a list of column names obeying a certain string length.
*
* This is especially important for Oracle, since it does not allow identifiers larger than 30 chars,
* however building idents automatically for foreign keys, composite keys or such can easily create
* very long names.
*
* @param array $columnNames
* @param string $postfix
* @param int $maxSize
* @return string
*/
protected function _generateIdentifierName($columnNames, $postfix='', $maxSize=30)
{
$columnCount = count($columnNames);
$postfixLen = strlen($postfix);
$parts = array_map(function($columnName) use($columnCount, $postfixLen, $maxSize) {
return substr($columnName, -floor(($maxSize-$postfixLen)/$columnCount - 1));
}, $columnNames);
$parts[] = $postfix;
$identifier = trim(implode("_", $parts), '_');
// using implicit schema support of DB2 and Postgres there might be dots in the auto-generated
// identifier names which can easily be replaced by underscores.
$identifier = str_replace(".", "_", $identifier);
if (is_numeric(substr($identifier, 0, 1))) {
$identifier = "i" . substr($identifier, 0, strlen($identifier)-1);
}
return $identifier;
}
}<?php
/*
* $Id: Schema.php 6876 2009-12-06 23:11:35Z beberlei $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* Configuration for a Schema
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class SchemaConfig
{
/**
* @var bool
*/
protected $_hasExplicitForeignKeyIndexes = false;
/**
* @var int
*/
protected $_maxIdentifierLength = 63;
/**
* @return bool
*/
public function hasExplicitForeignKeyIndexes()
{
return $this->_hasExplicitForeignKeyIndexes;
}
/**
* @param bool $flag
*/
public function setExplicitForeignKeyIndexes($flag)
{
$this->_hasExplicitForeignKeyIndexes = (bool)$flag;
}
/**
* @param int $length
*/
public function setMaxIdentifierLength($length)
{
$this->_maxIdentifierLength = (int)$length;
}
/**
* @return int
*/
public function getMaxIdentifierLength()
{
return $this->_maxIdentifierLength;
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
use \Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Schema\Visitor\Visitor;
/**
* Object representation of a database column
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class Column extends AbstractAsset
{
/**
* @var \Doctrine\DBAL\Types\Type
*/
protected $_type;
/**
* @var int
*/
protected $_length = null;
/**
* @var int
*/
protected $_precision = 0;
/**
* @var int
*/
protected $_scale = 0;
/**
* @var bool
*/
protected $_unsigned = false;
/**
* @var bool
*/
protected $_fixed = false;
/**
* @var bool
*/
protected $_notnull = true;
/**
* @var string
*/
protected $_default = null;
/**
* @var bool
*/
protected $_autoincrement = false;
/**
* @var array
*/
protected $_platformOptions = array();
/**
* @var string
*/
protected $_columnDefinition = null;
/**
* Create a new Column
*
* @param string $columnName
* @param Doctrine\DBAL\Types\Type $type
* @param int $length
* @param bool $notNull
* @param mixed $default
* @param bool $unsigned
* @param bool $fixed
* @param int $precision
* @param int $scale
* @param array $platformOptions
*/
public function __construct($columnName, Type $type, array $options=array())
{
$this->_setName($columnName);
$this->setType($type);
$this->setOptions($options);
}
/**
* @param array $options
* @return Column
*/
public function setOptions(array $options)
{
foreach ($options AS $name => $value) {
$method = "set".$name;
if (method_exists($this, $method)) {
$this->$method($value);
}
}
return $this;
}
/**
* @param Type $type
* @return Column
*/
public function setType(Type $type)
{
$this->_type = $type;
return $this;
}
/**
* @param int $length
* @return Column
*/
public function setLength($length)
{
if($length !== null) {
$this->_length = (int)$length;
} else {
$this->_length = null;
}
return $this;
}
/**
* @param int $precision
* @return Column
*/
public function setPrecision($precision)
{
$this->_precision = (int)$precision;
return $this;
}
/**
* @param int $scale
* @return Column
*/
public function setScale($scale)
{
$this->_scale = $scale;
return $this;
}
/**
*
* @param bool $unsigned
* @return Column
*/
public function setUnsigned($unsigned)
{
$this->_unsigned = (bool)$unsigned;
return $this;
}
/**
*
* @param bool $fixed
* @return Column
*/
public function setFixed($fixed)
{
$this->_fixed = (bool)$fixed;
return $this;
}
/**
* @param bool $notnull
* @return Column
*/
public function setNotnull($notnull)
{
$this->_notnull = (bool)$notnull;
return $this;
}
/**
*
* @param mixed $default
* @return Column
*/
public function setDefault($default)
{
$this->_default = $default;
return $this;
}
/**
*
* @param array $platformOptions
* @return Column
*/
public function setPlatformOptions(array $platformOptions)
{
$this->_platformOptions = $platformOptions;
return $this;
}
/**
*
* @param string $name
* @param mixed $value
* @return Column
*/
public function setPlatformOption($name, $value)
{
$this->_platformOptions[$name] = $value;
return $this;
}
/**
*
* @param string
* @return Column
*/
public function setColumnDefinition($value)
{
$this->_columnDefinition = $value;
return $this;
}
public function getType()
{
return $this->_type;
}
public function getLength()
{
return $this->_length;
}
public function getPrecision()
{
return $this->_precision;
}
public function getScale()
{
return $this->_scale;
}
public function getUnsigned()
{
return $this->_unsigned;
}
public function getFixed()
{
return $this->_fixed;
}
public function getNotnull()
{
return $this->_notnull;
}
public function getDefault()
{
return $this->_default;
}
public function getPlatformOptions()
{
return $this->_platformOptions;
}
public function hasPlatformOption($name)
{
return isset($this->_platformOptions[$name]);
}
public function getPlatformOption($name)
{
return $this->_platformOptions[$name];
}
public function getColumnDefinition()
{
return $this->_columnDefinition;
}
public function getAutoincrement()
{
return $this->_autoincrement;
}
public function setAutoincrement($flag)
{
$this->_autoincrement = $flag;
return $this;
}
/**
* @param Visitor $visitor
*/
public function visit(\Doctrine\DBAL\Schema\Visitor $visitor)
{
$visitor->accept($this);
}
/**
* @return array
*/
public function toArray()
{
return array_merge(array(
'name' => $this->_name,
'type' => $this->_type,
'default' => $this->_default,
'notnull' => $this->_notnull,
'length' => $this->_length,
'precision' => $this->_precision,
'scale' => $this->_scale,
'fixed' => $this->_fixed,
'unsigned' => $this->_unsigned,
'autoincrement' => $this->_autoincrement,
'columnDefinition' => $this->_columnDefinition,
), $this->_platformOptions);
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* Marker interface for contraints
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
interface Constraint
{
public function getName();
public function getColumns();
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
use \Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* Schema Diff
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
* @license http://ez.no/licenses/new_bsd New BSD License
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class SchemaDiff
{
/**
* All added tables
*
* @var array(string=>ezcDbSchemaTable)
*/
public $newTables = array();
/**
* All changed tables
*
* @var array(string=>ezcDbSchemaTableDiff)
*/
public $changedTables = array();
/**
* All removed tables
*
* @var array(string=>Table)
*/
public $removedTables = array();
/**
* @var array
*/
public $newSequences = array();
/**
* @var array
*/
public $changedSequences = array();
/**
* @var array
*/
public $removedSequences = array();
/**
* @var array
*/
public $orphanedForeignKeys = array();
/**
* Constructs an SchemaDiff object.
*
* @param array(string=>Table) $newTables
* @param array(string=>TableDiff) $changedTables
* @param array(string=>bool) $removedTables
*/
public function __construct($newTables = array(), $changedTables = array(), $removedTables = array())
{
$this->newTables = $newTables;
$this->changedTables = $changedTables;
$this->removedTables = $removedTables;
}
/**
* The to save sql mode ensures that the following things don't happen:
*
* 1. Tables are deleted
* 2. Sequences are deleted
* 3. Foreign Keys which reference tables that would otherwise be deleted.
*
* This way it is ensured that assets are deleted which might not be relevant to the metadata schema at all.
*
* @param AbstractPlatform $platform
* @return array
*/
public function toSaveSql(AbstractPlatform $platform)
{
return $this->_toSql($platform, true);
}
/**
* @param AbstractPlatform $platform
* @return array
*/
public function toSql(AbstractPlatform $platform)
{
return $this->_toSql($platform, false);
}
/**
* @param AbstractPlatform $platform
* @param bool $saveMode
* @return array
*/
protected function _toSql(AbstractPlatform $platform, $saveMode = false)
{
$sql = array();
if ($platform->supportsForeignKeyConstraints() && $saveMode == false) {
foreach ($this->orphanedForeignKeys AS $orphanedForeignKey) {
$sql[] = $platform->getDropForeignKeySQL($orphanedForeignKey, $orphanedForeignKey->getLocalTableName());
}
}
if ($platform->supportsSequences() == true) {
foreach ($this->changedSequences AS $sequence) {
$sql[] = $platform->getDropSequenceSQL($sequence);
$sql[] = $platform->getCreateSequenceSQL($sequence);
}
if ($saveMode === false) {
foreach ($this->removedSequences AS $sequence) {
$sql[] = $platform->getDropSequenceSQL($sequence);
}
}
foreach ($this->newSequences AS $sequence) {
$sql[] = $platform->getCreateSequenceSQL($sequence);
}
}
$foreignKeySql = array();
foreach ($this->newTables AS $table) {
$sql = array_merge(
$sql,
$platform->getCreateTableSQL($table, AbstractPlatform::CREATE_INDEXES)
);
if ($platform->supportsForeignKeyConstraints()) {
foreach ($table->getForeignKeys() AS $foreignKey) {
$foreignKeySql[] = $platform->getCreateForeignKeySQL($foreignKey, $table);
}
}
}
$sql = array_merge($sql, $foreignKeySql);
if ($saveMode === false) {
foreach ($this->removedTables AS $table) {
$sql[] = $platform->getDropTableSQL($table);
}
}
foreach ($this->changedTables AS $tableDiff) {
$sql = array_merge($sql, $platform->getAlterTableSQL($tableDiff));
}
return $sql;
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Schema\Visitor\CreateSchemaSqlCollector;
use Doctrine\DBAL\Schema\Visitor\DropSchemaSqlCollector;
use Doctrine\DBAL\Schema\Visitor\Visitor;
/**
* Object representation of a database schema
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class Schema extends AbstractAsset
{
/**
* @var array
*/
protected $_tables = array();
/**
* @var array
*/
protected $_sequences = array();
/**
* @var SchemaConfig
*/
protected $_schemaConfig = false;
/**
* @param array $tables
* @param array $sequences
* @param array $views
* @param array $triggers
* @param SchemaConfig $schemaConfig
*/
public function __construct(array $tables=array(), array $sequences=array(), SchemaConfig $schemaConfig=null)
{
if ($schemaConfig == null) {
$schemaConfig = new SchemaConfig();
}
$this->_schemaConfig = $schemaConfig;
foreach ($tables AS $table) {
$this->_addTable($table);
}
foreach ($sequences AS $sequence) {
$this->_addSequence($sequence);
}
}
/**
* @return bool
*/
public function hasExplicitForeignKeyIndexes()
{
return $this->_schemaConfig->hasExplicitForeignKeyIndexes();
}
/**
* @param Table $table
*/
protected function _addTable(Table $table)
{
$tableName = strtolower($table->getName());
if(isset($this->_tables[$tableName])) {
throw SchemaException::tableAlreadyExists($tableName);
}
$this->_tables[$tableName] = $table;
$table->setSchemaConfig($this->_schemaConfig);
}
/**
* @param Sequence $sequence
*/
protected function _addSequence(Sequence $sequence)
{
$seqName = strtolower($sequence->getName());
if (isset($this->_sequences[$seqName])) {
throw SchemaException::sequenceAlreadyExists($seqName);
}
$this->_sequences[$seqName] = $sequence;
}
/**
* Get all tables of this schema.
*
* @return array
*/
public function getTables()
{
return $this->_tables;
}
/**
* @param string $tableName
* @return Table
*/
public function getTable($tableName)
{
$tableName = strtolower($tableName);
if (!isset($this->_tables[$tableName])) {
throw SchemaException::tableDoesNotExist($tableName);
}
return $this->_tables[$tableName];
}
/**
* Does this schema have a table with the given name?
*
* @param string $tableName
* @return Schema
*/
public function hasTable($tableName)
{
$tableName = strtolower($tableName);
return isset($this->_tables[$tableName]);
}
/**
* @param string $sequenceName
* @return bool
*/
public function hasSequence($sequenceName)
{
$sequenceName = strtolower($sequenceName);
return isset($this->_sequences[$sequenceName]);
}
/**
* @throws SchemaException
* @param string $sequenceName
* @return Doctrine\DBAL\Schema\Sequence
*/
public function getSequence($sequenceName)
{
$sequenceName = strtolower($sequenceName);
if(!$this->hasSequence($sequenceName)) {
throw SchemaException::sequenceDoesNotExist($sequenceName);
}
return $this->_sequences[$sequenceName];
}
/**
* @return Doctrine\DBAL\Schema\Sequence[]
*/
public function getSequences()
{
return $this->_sequences;
}
/**
* Create a new table
*
* @param string $tableName
* @return Table
*/
public function createTable($tableName)
{
$table = new Table($tableName);
$this->_addTable($table);
return $table;
}
/**
* Rename a table
*
* @param string $oldTableName
* @param string $newTableName
* @return Schema
*/
public function renameTable($oldTableName, $newTableName)
{
$table = $this->getTable($oldTableName);
$table->_setName($newTableName);
$this->dropTable($oldTableName);
$this->_addTable($table);
return $this;
}
/**
* Drop a table from the schema.
*
* @param string $tableName
* @return Schema
*/
public function dropTable($tableName)
{
$tableName = strtolower($tableName);
$table = $this->getTable($tableName);
unset($this->_tables[$tableName]);
return $this;
}
/**
* Create a new sequence
*
* @param string $sequenceName
* @param int $allocationSize
* @param int $initialValue
* @return Sequence
*/
public function createSequence($sequenceName, $allocationSize=1, $initialValue=1)
{
$seq = new Sequence($sequenceName, $allocationSize, $initialValue);
$this->_addSequence($seq);
return $seq;
}
/**
* @param string $sequenceName
* @return Schema
*/
public function dropSequence($sequenceName)
{
$sequenceName = strtolower($sequenceName);
unset($this->_sequences[$sequenceName]);
return $this;
}
/**
* Return an array of necessary sql queries to create the schema on the given platform.
*
* @param AbstractPlatform $platform
* @return array
*/
public function toSql(\Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{
$sqlCollector = new CreateSchemaSqlCollector($platform);
$this->visit($sqlCollector);
return $sqlCollector->getQueries();
}
/**
* Return an array of necessary sql queries to drop the schema on the given platform.
*
* @param AbstractPlatform $platform
* @return array
*/
public function toDropSql(\Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{
$dropSqlCollector = new DropSchemaSqlCollector($platform);
$this->visit($dropSqlCollector);
return $dropSqlCollector->getQueries();
}
/**
* @param Schema $toSchema
* @param AbstractPlatform $platform
*/
public function getMigrateToSql(Schema $toSchema, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{
$comparator = new Comparator();
$schemaDiff = $comparator->compare($this, $toSchema);
return $schemaDiff->toSql($platform);
}
/**
* @param Schema $fromSchema
* @param AbstractPlatform $platform
*/
public function getMigrateFromSql(Schema $fromSchema, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{
$comparator = new Comparator();
$schemaDiff = $comparator->compare($fromSchema, $this);
return $schemaDiff->toSql($platform);
}
/**
* @param Visitor $visitor
*/
public function visit(Visitor $visitor)
{
$visitor->acceptSchema($this);
foreach ($this->_tables AS $table) {
$table->visit($visitor);
}
foreach ($this->_sequences AS $sequence) {
$sequence->visit($visitor);
}
}
/**
* Cloning a Schema triggers a deep clone of all related assets.
*
* @return void
*/
public function __clone()
{
foreach ($this->_tables AS $k => $table) {
$this->_tables[$k] = clone $table;
}
foreach ($this->_sequences AS $k => $sequence) {
$this->_sequences[$k] = clone $sequence;
}
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* xxx
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Juozas Kaziukenas <juozas@juokaz.com>
* @version $Revision$
* @since 2.0
*/
class MsSqlSchemaManager extends AbstractSchemaManager
{
/**
* @override
*/
protected function _getPortableTableColumnDefinition($tableColumn)
{
$dbType = strtolower($tableColumn['TYPE_NAME']);
$autoincrement = false;
if (stripos($dbType, 'identity')) {
$dbType = trim(str_ireplace('identity', '', $dbType));
$autoincrement = true;
}
$type = array();
$unsigned = $fixed = null;
if (!isset($tableColumn['name'])) {
$tableColumn['name'] = '';
}
$default = $tableColumn['COLUMN_DEF'];
while ($default != ($default2 = preg_replace("/^\((.*)\)$/", '$1', $default))) {
$default = $default2;
}
$length = (int) $tableColumn['LENGTH'];
$type = $this->_platform->getDoctrineTypeMapping($dbType);
switch ($type) {
case 'char':
if ($tableColumn['LENGTH'] == '1') {
$type = 'boolean';
if (preg_match('/^(is|has)/', $tableColumn['name'])) {
$type = array_reverse($type);
}
}
$fixed = true;
break;
case 'text':
$fixed = false;
break;
}
switch ($dbType) {
case 'nchar':
case 'nvarchar':
case 'ntext':
// Unicode data requires 2 bytes per character
$length = $length / 2;
break;
}
$options = array(
'length' => ($length == 0 || !in_array($type, array('text', 'string'))) ? null : $length,
'unsigned' => (bool) $unsigned,
'fixed' => (bool) $fixed,
'default' => $default !== 'NULL' ? $default : null,
'notnull' => (bool) ($tableColumn['IS_NULLABLE'] != 'YES'),
'scale' => $tableColumn['SCALE'],
'precision' => $tableColumn['PRECISION'],
'autoincrement' => $autoincrement,
);
return new Column($tableColumn['COLUMN_NAME'], \Doctrine\DBAL\Types\Type::getType($type), $options);
}
/**
* @override
*/
protected function _getPortableTableIndexesList($tableIndexRows, $tableName=null)
{
$result = array();
foreach ($tableIndexRows AS $tableIndex) {
$indexName = $keyName = $tableIndex['index_name'];
if (strpos($tableIndex['index_description'], 'primary key') !== false) {
$keyName = 'primary';
}
$keyName = strtolower($keyName);
$result[$keyName] = array(
'name' => $indexName,
'columns' => explode(', ', $tableIndex['index_keys']),
'unique' => strpos($tableIndex['index_description'], 'unique') !== false,
'primary' => strpos($tableIndex['index_description'], 'primary key') !== false,
);
}
$indexes = array();
foreach ($result AS $indexKey => $data) {
$indexes[$indexKey] = new Index($data['name'], $data['columns'], $data['unique'], $data['primary']);
}
return $indexes;
}
/**
* @override
*/
public function _getPortableTableForeignKeyDefinition($tableForeignKey)
{
return new ForeignKeyConstraint(
(array) $tableForeignKey['ColumnName'],
$tableForeignKey['ReferenceTableName'],
(array) $tableForeignKey['ReferenceColumnName'],
$tableForeignKey['ForeignKey'],
array(
'onUpdate' => str_replace('_', ' ', $tableForeignKey['update_referential_action_desc']),
'onDelete' => str_replace('_', ' ', $tableForeignKey['delete_referential_action_desc']),
)
);
}
/**
* @override
*/
protected function _getPortableTableDefinition($table)
{
return $table['name'];
}
/**
* @override
*/
protected function _getPortableDatabaseDefinition($database)
{
return $database['name'];
}
/**
* @override
*/
protected function _getPortableViewDefinition($view)
{
// @todo
return new View($view['name'], null);
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema\Visitor;
use Doctrine\DBAL\Platforms\AbstractPlatform,
Doctrine\DBAL\Schema\Table,
Doctrine\DBAL\Schema\Schema,
Doctrine\DBAL\Schema\Column,
Doctrine\DBAL\Schema\ForeignKeyConstraint,
Doctrine\DBAL\Schema\Constraint,
Doctrine\DBAL\Schema\Sequence,
Doctrine\DBAL\Schema\Index;
/**
* Schema Visitor used for Validation or Generation purposes.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
interface Visitor
{
/**
* @param Schema $schema
*/
public function acceptSchema(Schema $schema);
/**
* @param Table $table
*/
public function acceptTable(Table $table);
/**
* @param Column $column
*/
public function acceptColumn(Table $table, Column $column);
/**
* @param Table $localTable
* @param ForeignKeyConstraint $fkConstraint
*/
public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint);
/**
* @param Table $table
* @param Index $index
*/
public function acceptIndex(Table $table, Index $index);
/**
* @param Sequence $sequence
*/
public function acceptSequence(Sequence $sequence);
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema\Visitor;
use Doctrine\DBAL\Platforms\AbstractPlatform,
Doctrine\DBAL\Schema\Table,
Doctrine\DBAL\Schema\Schema,
Doctrine\DBAL\Schema\Column,
Doctrine\DBAL\Schema\ForeignKeyConstraint,
Doctrine\DBAL\Schema\Constraint,
Doctrine\DBAL\Schema\Sequence,
Doctrine\DBAL\Schema\Index;
class CreateSchemaSqlCollector implements Visitor
{
/**
* @var array
*/
private $_createTableQueries = array();
/**
* @var array
*/
private $_createSequenceQueries = array();
/**
* @var array
*/
private $_createFkConstraintQueries = array();
/**
*
* @var \Doctrine\DBAL\Platforms\AbstractPlatform
*/
private $_platform = null;
/**
* @param AbstractPlatform $platform
*/
public function __construct(AbstractPlatform $platform)
{
$this->_platform = $platform;
}
/**
* @param Schema $schema
*/
public function acceptSchema(Schema $schema)
{
}
/**
* Generate DDL Statements to create the accepted table with all its dependencies.
*
* @param Table $table
*/
public function acceptTable(Table $table)
{
$this->_createTableQueries = array_merge($this->_createTableQueries,
$this->_platform->getCreateTableSQL($table)
);
}
public function acceptColumn(Table $table, Column $column)
{
}
/**
* @param Table $localTable
* @param ForeignKeyConstraint $fkConstraint
*/
public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint)
{
// Append the foreign key constraints SQL
if ($this->_platform->supportsForeignKeyConstraints()) {
$this->_createFkConstraintQueries = array_merge($this->_createFkConstraintQueries,
(array) $this->_platform->getCreateForeignKeySQL($fkConstraint, $localTable->getName())
);
}
}
/**
* @param Table $table
* @param Index $index
*/
public function acceptIndex(Table $table, Index $index)
{
}
/**
* @param Sequence $sequence
*/
public function acceptSequence(Sequence $sequence)
{
$this->_createSequenceQueries = array_merge(
$this->_createSequenceQueries, (array)$this->_platform->getCreateSequenceSQL($sequence)
);
}
/**
* @return array
*/
public function resetQueries()
{
$this->_createTableQueries = array();
$this->_createSequenceQueries = array();
$this->_createFkConstraintQueries = array();
}
/**
* Get all queries collected so far.
*
* @return array
*/
public function getQueries()
{
return array_merge(
$this->_createTableQueries,
$this->_createSequenceQueries,
$this->_createFkConstraintQueries
);
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema\Visitor;
use Doctrine\DBAL\Platforms\AbstractPlatform,
Doctrine\DBAL\Schema\Table,
Doctrine\DBAL\Schema\Schema,
Doctrine\DBAL\Schema\Column,
Doctrine\DBAL\Schema\ForeignKeyConstraint,
Doctrine\DBAL\Schema\Constraint,
Doctrine\DBAL\Schema\Sequence,
Doctrine\DBAL\Schema\Index;
/**
* Gather SQL statements that allow to completly drop the current schema.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class DropSchemaSqlCollector implements Visitor
{
/**
* @var array
*/
private $_constraints = array();
/**
* @var array
*/
private $_sequences = array();
/**
* @var array
*/
private $_tables = array();
/**
*
* @var \Doctrine\DBAL\Platforms\AbstractPlatform
*/
private $_platform = null;
/**
* @param AbstractPlatform $platform
*/
public function __construct(AbstractPlatform $platform)
{
$this->_platform = $platform;
}
/**
* @param Schema $schema
*/
public function acceptSchema(Schema $schema)
{
}
/**
* @param Table $table
*/
public function acceptTable(Table $table)
{
$this->_tables[] = $this->_platform->getDropTableSQL($table->getName());
}
/**
* @param Column $column
*/
public function acceptColumn(Table $table, Column $column)
{
}
/**
* @param Table $localTable
* @param ForeignKeyConstraint $fkConstraint
*/
public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint)
{
if (strlen($fkConstraint->getName()) == 0) {
throw SchemaException::namedForeignKeyRequired($localTable, $fkConstraint);
}
$this->_constraints[] = $this->_platform->getDropForeignKeySQL($fkConstraint->getName(), $localTable->getName());
}
/**
* @param Table $table
* @param Index $index
*/
public function acceptIndex(Table $table, Index $index)
{
}
/**
* @param Sequence $sequence
*/
public function acceptSequence(Sequence $sequence)
{
$this->_sequences[] = $this->_platform->getDropSequenceSQL($sequence->getName());
}
/**
* @return array
*/
public function clearQueries()
{
$this->_constraints = $this->_sequences = $this->_tables = array();
}
/**
* @return array
*/
public function getQueries()
{
return array_merge($this->_constraints, $this->_tables, $this->_sequences);
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Schema\Visitor\Visitor;
class ForeignKeyConstraint extends AbstractAsset implements Constraint
{
/**
* @var Table
*/
protected $_localTable;
/**
* @var array
*/
protected $_localColumnNames;
/**
* @var string
*/
protected $_foreignTableName;
/**
* @var array
*/
protected $_foreignColumnNames;
/**
* @var string
*/
protected $_cascade = '';
/**
* @var array
*/
protected $_options;
/**
*
* @param array $localColumnNames
* @param string $foreignTableName
* @param array $foreignColumnNames
* @param string $cascade
* @param string|null $name
*/
public function __construct(array $localColumnNames, $foreignTableName, array $foreignColumnNames, $name=null, array $options=array())
{
$this->_setName($name);
$this->_localColumnNames = $localColumnNames;
$this->_foreignTableName = $foreignTableName;
$this->_foreignColumnNames = $foreignColumnNames;
$this->_options = $options;
}
/**
* @return string
*/
public function getLocalTableName()
{
return $this->_localTable->getName();
}
/**
* @param Table $table
*/
public function setLocalTable(Table $table)
{
$this->_localTable = $table;
}
/**
* @return array
*/
public function getLocalColumns()
{
return $this->_localColumnNames;
}
public function getColumns()
{
return $this->_localColumnNames;
}
/**
* @return string
*/
public function getForeignTableName()
{
return $this->_foreignTableName;
}
/**
* @return array
*/
public function getForeignColumns()
{
return $this->_foreignColumnNames;
}
public function hasOption($name)
{
return isset($this->_options[$name]);
}
public function getOption($name)
{
return $this->_options[$name];
}
/**
* Foreign Key onUpdate status
*
* @return string|null
*/
public function onUpdate()
{
return $this->_onEvent('onUpdate');
}
/**
* Foreign Key onDelete status
*
* @return string|null
*/
public function onDelete()
{
return $this->_onEvent('onDelete');
}
/**
* @param string $event
* @return string|null
*/
private function _onEvent($event)
{
if (isset($this->_options[$event])) {
$onEvent = strtoupper($this->_options[$event]);
if (!in_array($onEvent, array('NO ACTION', 'RESTRICT'))) {
return $onEvent;
}
}
return false;
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Schema\Visitor\Visitor;
use Doctrine\DBAL\DBALException;
/**
* Object Representation of a table
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class Table extends AbstractAsset
{
/**
* @var string
*/
protected $_name = null;
/**
* @var array
*/
protected $_columns = array();
/**
* @var array
*/
protected $_indexes = array();
/**
* @var string
*/
protected $_primaryKeyName = false;
/**
* @var array
*/
protected $_fkConstraints = array();
/**
* @var array
*/
protected $_options = array();
/**
* @var SchemaConfig
*/
protected $_schemaConfig = null;
/**
*
* @param string $tableName
* @param array $columns
* @param array $indexes
* @param array $fkConstraints
* @param int $idGeneratorType
* @param array $options
*/
public function __construct($tableName, array $columns=array(), array $indexes=array(), array $fkConstraints=array(), $idGeneratorType = 0, array $options=array())
{
if (strlen($tableName) == 0) {
throw DBALException::invalidTableName($tableName);
}
$this->_setName($tableName);
$this->_idGeneratorType = $idGeneratorType;
foreach ($columns AS $column) {
$this->_addColumn($column);
}
foreach ($indexes AS $idx) {
$this->_addIndex($idx);
}
foreach ($fkConstraints AS $constraint) {
$this->_addForeignKeyConstraint($constraint);
}
$this->_options = $options;
}
/**
* @param SchemaConfig $schemaConfig
*/
public function setSchemaConfig(SchemaConfig $schemaConfig)
{
$this->_schemaConfig = $schemaConfig;
}
/**
* @return int
*/
protected function _getMaxIdentifierLength()
{
if ($this->_schemaConfig instanceof SchemaConfig) {
return $this->_schemaConfig->getMaxIdentifierLength();
} else {
return 63;
}
}
/**
* Set Primary Key
*
* @param array $columns
* @param string $indexName
* @return Table
*/
public function setPrimaryKey(array $columns, $indexName = false)
{
$primaryKey = $this->_createIndex($columns, $indexName ?: "primary", true, true);
foreach ($columns AS $columnName) {
$column = $this->getColumn($columnName);
$column->setNotnull(true);
}
return $primaryKey;
}
/**
* @param array $columnNames
* @param string $indexName
* @return Table
*/
public function addIndex(array $columnNames, $indexName = null)
{
if($indexName == null) {
$indexName = $this->_generateIdentifierName(
array_merge(array($this->getName()), $columnNames), "idx", $this->_getMaxIdentifierLength()
);
}
return $this->_createIndex($columnNames, $indexName, false, false);
}
/**
*
* @param array $columnNames
* @param string $indexName
* @return Table
*/
public function addUniqueIndex(array $columnNames, $indexName = null)
{
if ($indexName == null) {
$indexName = $this->_generateIdentifierName(
array_merge(array($this->getName()), $columnNames), "uniq", $this->_getMaxIdentifierLength()
);
}
return $this->_createIndex($columnNames, $indexName, true, false);
}
/**
* Check if an index begins in the order of the given columns.
*
* @param array $columnsNames
* @return bool
*/
public function columnsAreIndexed(array $columnsNames)
{
foreach ($this->getIndexes() AS $index) {
/* @var $index Index */
if ($index->spansColumns($columnsNames)) {
return true;
}
}
return false;
}
/**
*
* @param array $columnNames
* @param string $indexName
* @param bool $isUnique
* @param bool $isPrimary
* @return Table
*/
private function _createIndex(array $columnNames, $indexName, $isUnique, $isPrimary)
{
if (preg_match('(([^a-zA-Z0-9_]+))', $indexName)) {
throw SchemaException::indexNameInvalid($indexName);
}
foreach ($columnNames AS $columnName => $indexColOptions) {
if (is_numeric($columnName) && is_string($indexColOptions)) {
$columnName = $indexColOptions;
}
if ( ! $this->hasColumn($columnName)) {
throw SchemaException::columnDoesNotExist($columnName, $this->_name);
}
}
$this->_addIndex(new Index($indexName, $columnNames, $isUnique, $isPrimary));
return $this;
}
/**
* @param string $columnName
* @param string $columnType
* @param array $options
* @return Column
*/
public function addColumn($columnName, $typeName, array $options=array())
{
$column = new Column($columnName, Type::getType($typeName), $options);
$this->_addColumn($column);
return $column;
}
/**
* Rename Column
*
* @param string $oldColumnName
* @param string $newColumnName
* @return Table
*/
public function renameColumn($oldColumnName, $newColumnName)
{
$column = $this->getColumn($oldColumnName);
$this->dropColumn($oldColumnName);
$column->_setName($newColumnName);
return $this;
}
/**
* Change Column Details
*
* @param string $columnName
* @param array $options
* @return Table
*/
public function changeColumn($columnName, array $options)
{
$column = $this->getColumn($columnName);
$column->setOptions($options);
return $this;
}
/**
* Drop Column from Table
*
* @param string $columnName
* @return Table
*/
public function dropColumn($columnName)
{
$columnName = strtolower($columnName);
$column = $this->getColumn($columnName);
unset($this->_columns[$columnName]);
return $this;
}
/**
* Add a foreign key constraint
*
* Name is inferred from the local columns
*
* @param Table $foreignTable
* @param array $localColumns
* @param array $foreignColumns
* @param array $options
* @return Table
*/
public function addForeignKeyConstraint($foreignTable, array $localColumnNames, array $foreignColumnNames, array $options=array())
{
$name = $this->_generateIdentifierName(array_merge((array)$this->getName(), $localColumnNames), "fk", $this->_getMaxIdentifierLength());
return $this->addNamedForeignKeyConstraint($name, $foreignTable, $localColumnNames, $foreignColumnNames, $options);
}
/**
* Add a foreign key constraint
*
* Name is to be generated by the database itsself.
*
* @param Table $foreignTable
* @param array $localColumns
* @param array $foreignColumns
* @param array $options
* @return Table
*/
public function addUnnamedForeignKeyConstraint($foreignTable, array $localColumnNames, array $foreignColumnNames, array $options=array())
{
return $this->addNamedForeignKeyConstraint(null, $foreignTable, $localColumnNames, $foreignColumnNames, $options);
}
/**
* Add a foreign key constraint with a given name
*
* @param string $name
* @param Table $foreignTable
* @param array $localColumns
* @param array $foreignColumns
* @param array $options
* @return Table
*/
public function addNamedForeignKeyConstraint($name, $foreignTable, array $localColumnNames, array $foreignColumnNames, array $options=array())
{
if ($foreignTable instanceof Table) {
$foreignTableName = $foreignTable->getName();
foreach ($foreignColumnNames AS $columnName) {
if ( ! $foreignTable->hasColumn($columnName)) {
throw SchemaException::columnDoesNotExist($columnName, $foreignTable->getName());
}
}
} else {
$foreignTableName = $foreignTable;
}
foreach ($localColumnNames AS $columnName) {
if ( ! $this->hasColumn($columnName)) {
throw SchemaException::columnDoesNotExist($columnName, $this->_name);
}
}
$constraint = new ForeignKeyConstraint(
$localColumnNames, $foreignTableName, $foreignColumnNames, $name, $options
);
$this->_addForeignKeyConstraint($constraint);
return $this;
}
/**
* @param string $name
* @param string $value
* @return Table
*/
public function addOption($name, $value)
{
$this->_options[$name] = $value;
return $this;
}
/**
* @param Column $column
*/
protected function _addColumn(Column $column)
{
$columnName = $column->getName();
$columnName = strtolower($columnName);
if (isset($this->_columns[$columnName])) {
throw SchemaException::columnAlreadyExists($this->getName(), $columnName);
}
$this->_columns[$columnName] = $column;
}
/**
* Add index to table
*
* @param Index $indexCandidate
* @return Table
*/
protected function _addIndex(Index $indexCandidate)
{
// check for duplicates
foreach ($this->_indexes AS $existingIndex) {
if ($indexCandidate->isFullfilledBy($existingIndex)) {
return $this;
}
}
$indexName = $indexCandidate->getName();
$indexName = strtolower($indexName);
if (isset($this->_indexes[$indexName]) || ($this->_primaryKeyName != false && $indexCandidate->isPrimary())) {
throw SchemaException::indexAlreadyExists($indexName, $this->_name);
}
// remove overruled indexes
foreach ($this->_indexes AS $idxKey => $existingIndex) {
if ($indexCandidate->overrules($existingIndex)) {
unset($this->_indexes[$idxKey]);
}
}
if ($indexCandidate->isPrimary()) {
$this->_primaryKeyName = $indexName;
}
$this->_indexes[$indexName] = $indexCandidate;
return $this;
}
/**
* @param ForeignKeyConstraint $constraint
*/
protected function _addForeignKeyConstraint(ForeignKeyConstraint $constraint)
{
$constraint->setLocalTable($this);
if(strlen($constraint->getName())) {
$name = $constraint->getName();
} else {
$name = $this->_generateIdentifierName(
array_merge((array)$this->getName(), $constraint->getLocalColumns()), "fk", $this->_getMaxIdentifierLength()
);
}
$name = strtolower($name);
$this->_fkConstraints[$name] = $constraint;
// add an explicit index on the foreign key columns. If there is already an index that fullfils this requirements drop the request.
// In the case of __construct calling this method during hydration from schema-details all the explicitly added indexes
// lead to duplicates. This creates compuation overhead in this case, however no duplicate indexes are ever added (based on columns).
$this->addIndex($constraint->getColumns());
}
/**
* Does Table have a foreign key constraint with the given name?
* *
* @param string $constraintName
* @return bool
*/
public function hasForeignKey($constraintName)
{
$constraintName = strtolower($constraintName);
return isset($this->_fkConstraints[$constraintName]);
}
/**
* @param string $constraintName
* @return ForeignKeyConstraint
*/
public function getForeignKey($constraintName)
{
$constraintName = strtolower($constraintName);
if(!$this->hasForeignKey($constraintName)) {
throw SchemaException::foreignKeyDoesNotExist($constraintName, $this->_name);
}
return $this->_fkConstraints[$constraintName];
}
/**
* @return Column[]
*/
public function getColumns()
{
$columns = $this->_columns;
$pkCols = array();
$fkCols = array();
if ($this->hasIndex($this->_primaryKeyName)) {
$pkCols = $this->getPrimaryKey()->getColumns();
}
foreach ($this->getForeignKeys() AS $fk) {
/* @var $fk ForeignKeyConstraint */
$fkCols = array_merge($fkCols, $fk->getColumns());
}
$colNames = array_unique(array_merge($pkCols, $fkCols, array_keys($columns)));
uksort($columns, function($a, $b) use($colNames) {
return (array_search($a, $colNames) >= array_search($b, $colNames));
});
return $columns;
}
/**
* Does this table have a column with the given name?
*
* @param string $columnName
* @return bool
*/
public function hasColumn($columnName)
{
$columnName = strtolower($columnName);
return isset($this->_columns[$columnName]);
}
/**
* Get a column instance
*
* @param string $columnName
* @return Column
*/
public function getColumn($columnName)
{
$columnName = strtolower($columnName);
if (!$this->hasColumn($columnName)) {
throw SchemaException::columnDoesNotExist($columnName, $this->_name);
}
return $this->_columns[$columnName];
}
/**
* @return Index
*/
public function getPrimaryKey()
{
return $this->getIndex($this->_primaryKeyName);
}
/**
* @param string $indexName
* @return bool
*/
public function hasIndex($indexName)
{
$indexName = strtolower($indexName);
return (isset($this->_indexes[$indexName]));
}
/**
* @param string $indexName
* @return Index
*/
public function getIndex($indexName)
{
$indexName = strtolower($indexName);
if (!$this->hasIndex($indexName)) {
throw SchemaException::indexDoesNotExist($indexName, $this->_name);
}
return $this->_indexes[$indexName];
}
/**
* @return array
*/
public function getIndexes()
{
return $this->_indexes;
}
/**
* Get Constraints
*
* @return array
*/
public function getForeignKeys()
{
return $this->_fkConstraints;
}
public function hasOption($name)
{
return isset($this->_options[$name]);
}
public function getOption($name)
{
return $this->_options[$name];
}
public function getOptions()
{
return $this->_options;
}
/**
* @param Visitor $visitor
*/
public function visit(Visitor $visitor)
{
$visitor->acceptTable($this);
foreach ($this->getColumns() AS $column) {
$visitor->acceptColumn($this, $column);
}
foreach ($this->getIndexes() AS $index) {
$visitor->acceptIndex($this, $index);
}
foreach ($this->getForeignKeys() AS $constraint) {
$visitor->acceptForeignKey($this, $constraint);
}
}
/**
* Clone of a Table triggers a deep clone of all affected assets
*/
public function __clone()
{
foreach ($this->_columns AS $k => $column) {
$this->_columns[$k] = clone $column;
}
foreach ($this->_indexes AS $k => $index) {
$this->_indexes[$k] = clone $index;
}
foreach ($this->_fkConstraints AS $k => $fk) {
$this->_fkConstraints[$k] = clone $fk;
$this->_fkConstraints[$k]->setLocalTable($this);
}
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* Table Diff
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
* @license http://ez.no/licenses/new_bsd New BSD License
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class TableDiff
{
/**
* @var string
*/
public $name = null;
/**
* @var string
*/
public $newName = false;
/**
* All added fields
*
* @var array(string=>Column)
*/
public $addedColumns;
/**
* All changed fields
*
* @var array(string=>Column)
*/
public $changedColumns = array();
/**
* All removed fields
*
* @var array(string=>bool)
*/
public $removedColumns = array();
/**
* Columns that are only renamed from key to column instance name.
*
* @var array(string=>Column)
*/
public $renamedColumns = array();
/**
* All added indexes
*
* @var array(string=>Index)
*/
public $addedIndexes = array();
/**
* All changed indexes
*
* @var array(string=>Index)
*/
public $changedIndexes = array();
/**
* All removed indexes
*
* @var array(string=>bool)
*/
public $removedIndexes = array();
/**
* All added foreign key definitions
*
* @var array
*/
public $addedForeignKeys = array();
/**
* All changed foreign keys
*
* @var array
*/
public $changedForeignKeys = array();
/**
* All removed foreign keys
*
* @var array
*/
public $removedForeignKeys = array();
/**
* Constructs an TableDiff object.
*
* @param array(string=>Column) $addedColumns
* @param array(string=>Column) $changedColumns
* @param array(string=>bool) $removedColumns
* @param array(string=>Index) $addedIndexes
* @param array(string=>Index) $changedIndexes
* @param array(string=>bool) $removedIndexes
*/
public function __construct($tableName, $addedColumns = array(),
$changedColumns = array(), $removedColumns = array(), $addedIndexes = array(),
$changedIndexes = array(), $removedIndexes = array())
{
$this->name = $tableName;
$this->addedColumns = $addedColumns;
$this->changedColumns = $changedColumns;
$this->removedColumns = $removedColumns;
$this->addedIndexes = $addedIndexes;
$this->changedIndexes = $changedIndexes;
$this->removedIndexes = $removedIndexes;
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* Oracle Schema Manager
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @version $Revision$
* @since 2.0
*/
class OracleSchemaManager extends AbstractSchemaManager
{
protected function _getPortableViewDefinition($view)
{
$view = \array_change_key_case($view, CASE_LOWER);
return new View($view['view_name'], $view['text']);
}
protected function _getPortableUserDefinition($user)
{
$user = \array_change_key_case($user, CASE_LOWER);
return array(
'user' => $user['username'],
);
}
protected function _getPortableTableDefinition($table)
{
$table = \array_change_key_case($table, CASE_LOWER);
return $table['table_name'];
}
/**
* @license New BSD License
* @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html
* @param array $tableIndexes
* @param string $tableName
* @return array
*/
protected function _getPortableTableIndexesList($tableIndexes, $tableName=null)
{
$indexBuffer = array();
foreach ( $tableIndexes as $tableIndex ) {
$tableIndex = \array_change_key_case($tableIndex, CASE_LOWER);
$keyName = strtolower($tableIndex['name']);
if ( strtolower($tableIndex['is_primary']) == "p" ) {
$keyName = 'primary';
$buffer['primary'] = true;
$buffer['non_unique'] = false;
} else {
$buffer['primary'] = false;
$buffer['non_unique'] = ( $tableIndex['is_unique'] == 0 ) ? true : false;
}
$buffer['key_name'] = $keyName;
$buffer['column_name'] = $tableIndex['column_name'];
$indexBuffer[] = $buffer;
}
return parent::_getPortableTableIndexesList($indexBuffer, $tableName);
}
protected function _getPortableTableColumnDefinition($tableColumn)
{
$tableColumn = \array_change_key_case($tableColumn, CASE_LOWER);
$dbType = strtolower($tableColumn['data_type']);
if(strpos($dbType, "timestamp(") === 0) {
if (strpos($dbType, "WITH TIME ZONE")) {
$dbType = "timestamptz";
} else {
$dbType = "timestamp";
}
}
$type = array();
$length = $unsigned = $fixed = null;
if ( ! empty($tableColumn['data_length'])) {
$length = $tableColumn['data_length'];
}
if ( ! isset($tableColumn['column_name'])) {
$tableColumn['column_name'] = '';
}
if (stripos($tableColumn['data_default'], 'NULL') !== null) {
$tableColumn['data_default'] = null;
}
$precision = null;
$scale = null;
$type = $this->_platform->getDoctrineTypeMapping($dbType);
switch ($dbType) {
case 'number':
// @todo this sucks for the mapping stuff, is this deterministic maybe?
if($tableColumn['data_scale'] > 0) {
$precision = $tableColumn['data_precision'];
$scale = $tableColumn['data_scale'];
if ($precision == 0 && $scale == 1) {
$type = 'boolean';
} else {
$type = 'decimal';
}
}
$length = null;
break;
case 'pls_integer':
case 'binary_integer':
$length = null;
break;
case 'varchar':
case 'varchar2':
case 'nvarchar2':
$fixed = false;
break;
case 'char':
case 'nchar':
$fixed = true;
break;
case 'date':
case 'timestamp':
$length = null;
break;
case 'float':
$precision = $tableColumn['data_precision'];
$scale = $tableColumn['data_scale'];
$length = null;
break;
case 'clob':
case 'nclob':
$length = null;
break;
case 'blob':
case 'raw':
case 'long raw':
case 'bfile':
$length = null;
break;
case 'rowid':
case 'urowid':
default:
$length = null;
}
$options = array(
'notnull' => (bool) ($tableColumn['nullable'] === 'N'),
'fixed' => (bool) $fixed,
'unsigned' => (bool) $unsigned,
'default' => $tableColumn['data_default'],
'length' => $length,
'precision' => $precision,
'scale' => $scale,
'platformDetails' => array(),
);
return new Column($tableColumn['column_name'], \Doctrine\DBAL\Types\Type::getType($type), $options);
}
protected function _getPortableTableForeignKeysList($tableForeignKeys)
{
$list = array();
foreach ($tableForeignKeys as $key => $value) {
$value = \array_change_key_case($value, CASE_LOWER);
if (!isset($list[$value['constraint_name']])) {
if ($value['delete_rule'] == "NO ACTION") {
$value['delete_rule'] = null;
}
$list[$value['constraint_name']] = array(
'name' => $value['constraint_name'],
'local' => array(),
'foreign' => array(),
'foreignTable' => $value['references_table'],
'onDelete' => $value['delete_rule'],
);
}
$list[$value['constraint_name']]['local'][$value['position']] = $value['local_column'];
$list[$value['constraint_name']]['foreign'][$value['position']] = $value['foreign_column'];
}
$result = array();
foreach($list AS $constraint) {
$result[] = new ForeignKeyConstraint(
array_values($constraint['local']), $constraint['foreignTable'],
array_values($constraint['foreign']), $constraint['name'],
array('onDelete' => $constraint['onDelete'])
);
}
return $result;
}
protected function _getPortableSequenceDefinition($sequence)
{
$sequence = \array_change_key_case($sequence, CASE_LOWER);
return new Sequence($sequence['sequence_name'], $sequence['increment_by'], $sequence['min_value']);
}
protected function _getPortableFunctionDefinition($function)
{
$function = \array_change_key_case($function, CASE_LOWER);
return $function['name'];
}
protected function _getPortableDatabaseDefinition($database)
{
$database = \array_change_key_case($database, CASE_LOWER);
return $database['username'];
}
public function createDatabase($database = null)
{
if (is_null($database)) {
$database = $this->_conn->getDatabase();
}
$params = $this->_conn->getParams();
$username = $database;
$password = $params['password'];
$query = 'CREATE USER ' . $username . ' IDENTIFIED BY ' . $password;
$result = $this->_conn->executeUpdate($query);
$query = 'GRANT CREATE SESSION, CREATE TABLE, UNLIMITED TABLESPACE, CREATE SEQUENCE, CREATE TRIGGER TO ' . $username;
$result = $this->_conn->executeUpdate($query);
return true;
}
public function dropAutoincrement($table)
{
$sql = $this->_platform->getDropAutoincrementSql($table);
foreach ($sql as $query) {
$this->_conn->executeUpdate($query);
}
return true;
}
public function dropTable($name)
{
$this->dropAutoincrement($name);
return parent::dropTable($name);
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Schema\Visitor\Visitor;
/**
* Sequence Structure
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class Sequence extends AbstractAsset
{
/**
* @var int
*/
protected $_allocationSize = 1;
/**
* @var int
*/
protected $_initialValue = 1;
/**
*
* @param string $name
* @param int $allocationSize
* @param int $initialValue
*/
public function __construct($name, $allocationSize=1, $initialValue=1)
{
$this->_setName($name);
$this->_allocationSize = (is_numeric($allocationSize))?$allocationSize:1;
$this->_initialValue = (is_numeric($initialValue))?$initialValue:1;
}
public function getAllocationSize()
{
return $this->_allocationSize;
}
public function getInitialValue()
{
return $this->_initialValue;
}
/**
* @param Visitor $visitor
*/
public function visit(Visitor $visitor)
{
$visitor->acceptSequence($this);
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* Represent the change of a column
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class ColumnDiff
{
public $oldColumnName;
/**
* @var Column
*/
public $column;
/**
* @var array
*/
public $changedProperties = array();
public function __construct($oldColumnName, Column $column, array $changedProperties = array())
{
$this->oldColumnName = $oldColumnName;
$this->column = $column;
$this->changedProperties = $changedProperties;
}
public function hasChanged($propertyName)
{
return in_array($propertyName, $this->changedProperties);
}
}<?php
namespace Doctrine\DBAL\Schema;
class SchemaException extends \Doctrine\DBAL\DBALException
{
const TABLE_DOESNT_EXIST = 10;
const TABLE_ALREADY_EXISTS = 20;
const COLUMN_DOESNT_EXIST = 30;
const COLUMN_ALREADY_EXISTS = 40;
const INDEX_DOESNT_EXIST = 50;
const INDEX_ALREADY_EXISTS = 60;
const SEQUENCE_DOENST_EXIST = 70;
const SEQUENCE_ALREADY_EXISTS = 80;
const INDEX_INVALID_NAME = 90;
const FOREIGNKEY_DOESNT_EXIST = 100;
/**
* @param string $tableName
* @return SchemaException
*/
static public function tableDoesNotExist($tableName)
{
return new self("There is no table with name '".$tableName."' in the schema.", self::TABLE_DOESNT_EXIST);
}
/**
* @param string $indexName
* @return SchemaException
*/
static public function indexNameInvalid($indexName)
{
return new self("Invalid index-name $indexName given, has to be [a-zA-Z0-9_]", self::INDEX_INVALID_NAME);
}
/**
* @param string $indexName
* @return SchemaException
*/
static public function indexDoesNotExist($indexName, $table)
{
return new self("Index '$indexName' does not exist on table '$table'.", self::INDEX_DOESNT_EXIST);
}
/**
* @param string $indexName
* @return SchemaException
*/
static public function indexAlreadyExists($indexName, $table)
{
return new self("An index with name '$indexName' was already defined on table '$table'.", self::INDEX_ALREADY_EXISTS);
}
/**
* @param string $columnName
* @return SchemaException
*/
static public function columnDoesNotExist($columnName, $table)
{
return new self("There is no column with name '$columnName' on table '$table'.", self::COLUMN_DOESNT_EXIST);
}
/**
*
* @param string $tableName
* @return SchemaException
*/
static public function tableAlreadyExists($tableName)
{
return new self("The table with name '".$tableName."' already exists.", self::TABLE_ALREADY_EXISTS);
}
/**
*
* @param string $tableName
* @param string $columnName
* @return SchemaException
*/
static public function columnAlreadyExists($tableName, $columnName)
{
return new self(
"The column '".$columnName."' on table '".$tableName."' already exists.", self::COLUMN_ALREADY_EXISTS
);
}
/**
* @param string $sequenceName
* @return SchemaException
*/
static public function sequenceAlreadyExists($sequenceName)
{
return new self("The sequence '".$sequenceName."' already exists.", self::SEQUENCE_ALREADY_EXISTS);
}
/**
* @param string $sequenceName
* @return SchemaException
*/
static public function sequenceDoesNotExist($sequenceName)
{
return new self("There exists no sequence with the name '".$sequenceName."'.", self::SEQUENCE_DOENST_EXIST);
}
/**
* @param string $fkName
* @return SchemaException
*/
static public function foreignKeyDoesNotExist($fkName, $table)
{
return new self("There exists no foreign key with the name '$fkName' on table '$table'.", self::FOREIGNKEY_DOESNT_EXIST);
}
static public function namedForeignKeyRequired(Table $localTable, ForeignKeyConstraint $foreignKey)
{
return new self(
"The performed schema operation on ".$localTable->getName()." requires a named foreign key, ".
"but the given foreign key from (".implode(", ", $foreignKey->getColumns()).") onto foreign table ".
"'".$foreignKey->getForeignTableName()."' (".implode(", ", $foreignKey->getForeignColumns()).") is currently ".
"unnamed."
);
}
static public function alterTableChangeNotSupported($changeName) {
return new self ("Alter table change not supported, given '$changeName'");
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL;
/**
* Contains all DBAL LockModes
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 1.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Roman Borschel <roman@code-factory.org>
*/
class LockMode
{
const NONE = 0;
const OPTIMISTIC = 1;
const PESSIMISTIC_READ = 2;
const PESSIMISTIC_WRITE = 4;
final private function __construct() { }
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL;
/**
* Driver interface.
* Interface that all DBAL drivers must implement.
*
* @since 2.0
*/
interface Driver
{
/**
* Attempts to create a connection with the database.
*
* @param array $params All connection parameters passed by the user.
* @param string $username The username to use when connecting.
* @param string $password The password to use when connecting.
* @param array $driverOptions The driver options to use when connecting.
* @return Doctrine\DBAL\Driver\Connection The database connection.
*/
public function connect(array $params, $username = null, $password = null, array $driverOptions = array());
/**
* Gets the DatabasePlatform instance that provides all the metadata about
* the platform this driver connects to.
*
* @return Doctrine\DBAL\Platforms\AbstractPlatform The database platform.
*/
public function getDatabasePlatform();
/**
* Gets the SchemaManager that can be used to inspect and change the underlying
* database schema of the platform this driver connects to.
*
* @param Doctrine\DBAL\Connection $conn
* @return Doctrine\DBAL\SchemaManager
*/
public function getSchemaManager(Connection $conn);
/**
* Gets the name of the driver.
*
* @return string The name of the driver.
*/
public function getName();
/**
* Get the name of the database connected to for this driver.
*
* @param Doctrine\DBAL\Connection $conn
* @return string $database
*/
public function getDatabase(Connection $conn);
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms;
use Doctrine\DBAL\Schema\TableDiff,
Doctrine\DBAL\Schema\Table;
/**
* PostgreSqlPlatform.
*
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @todo Rename: PostgreSQLPlatform
*/
class PostgreSqlPlatform extends AbstractPlatform
{
/**
* Returns part of a string.
*
* Note: Not SQL92, but common functionality.
*
* @param string $value the target $value the string or the string column.
* @param int $from extract from this characeter.
* @param int $len extract this amount of characters.
* @return string sql that extracts part of a string.
* @override
*/
public function getSubstringExpression($value, $from, $len = null)
{
if ($len === null) {
return 'SUBSTR(' . $value . ', ' . $from . ')';
} else {
return 'SUBSTR(' . $value . ', ' . $from . ', ' . $len . ')';
}
}
/**
* Returns the SQL string to return the current system date and time.
*
* @return string
*/
public function getNowExpression()
{
return 'LOCALTIMESTAMP(0)';
}
/**
* regexp
*
* @return string the regular expression operator
* @override
*/
public function getRegexpExpression()
{
return 'SIMILAR TO';
}
/**
* returns the position of the first occurrence of substring $substr in string $str
*
* @param string $substr literal string to find
* @param string $str literal string
* @param int $pos position to start at, beginning of string by default
* @return integer
*/
public function getLocateExpression($str, $substr, $startPos = false)
{
if ($startPos !== false) {
$str = $this->getSubstringExpression($str, $startPos);
return 'CASE WHEN (POSITION('.$substr.' IN '.$str.') = 0) THEN 0 ELSE (POSITION('.$substr.' IN '.$str.') + '.($startPos-1).') END';
} else {
return 'POSITION('.$substr.' IN '.$str.')';
}
}
/**
* parses a literal boolean value and returns
* proper sql equivalent
*
* @param string $value boolean value to be parsed
* @return string parsed boolean value
*/
/*public function parseBoolean($value)
{
return $value;
}*/
/**
* Whether the platform supports sequences.
* Postgres has native support for sequences.
*
* @return boolean
*/
public function supportsSequences()
{
return true;
}
/**
* Whether the platform supports database schemas.
*
* @return boolean
*/
public function supportsSchemas()
{
return true;
}
/**
* Whether the platform supports identity columns.
* Postgres supports these through the SERIAL keyword.
*
* @return boolean
*/
public function supportsIdentityColumns()
{
return true;
}
/**
* Whether the platform prefers sequences for ID generation.
*
* @return boolean
*/
public function prefersSequences()
{
return true;
}
public function getListDatabasesSQL()
{
return 'SELECT datname FROM pg_database';
}
public function getListSequencesSQL($database)
{
return "SELECT
relname
FROM
pg_class
WHERE relkind = 'S' AND relnamespace IN
(SELECT oid FROM pg_namespace
WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema')";
}
public function getListTablesSQL()
{
return "SELECT
c.relname AS table_name
FROM pg_class c, pg_user u
WHERE c.relowner = u.usesysid
AND c.relkind = 'r'
AND NOT EXISTS (SELECT 1 FROM pg_views WHERE viewname = c.relname)
AND c.relname !~ '^(pg_|sql_)'
UNION
SELECT c.relname AS table_name
FROM pg_class c
WHERE c.relkind = 'r'
AND NOT EXISTS (SELECT 1 FROM pg_views WHERE viewname = c.relname)
AND NOT EXISTS (SELECT 1 FROM pg_user WHERE usesysid = c.relowner)
AND c.relname !~ '^pg_'";
}
public function getListViewsSQL($database)
{
return 'SELECT viewname, definition FROM pg_views';
}
public function getListTableForeignKeysSQL($table, $database = null)
{
return "SELECT r.conname, pg_catalog.pg_get_constraintdef(r.oid, true) as condef
FROM pg_catalog.pg_constraint r
WHERE r.conrelid =
(
SELECT c.oid
FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname = '" . $table . "' AND pg_catalog.pg_table_is_visible(c.oid)
)
AND r.contype = 'f'";
}
public function getCreateViewSQL($name, $sql)
{
return 'CREATE VIEW ' . $name . ' AS ' . $sql;
}
public function getDropViewSQL($name)
{
return 'DROP VIEW '. $name;
}
public function getListTableConstraintsSQL($table)
{
return "SELECT
relname
FROM
pg_class
WHERE oid IN (
SELECT indexrelid
FROM pg_index, pg_class
WHERE pg_class.relname = '$table'
AND pg_class.oid = pg_index.indrelid
AND (indisunique = 't' OR indisprimary = 't')
)";
}
/**
* @license New BSD License
* @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html
* @param string $table
* @return string
*/
public function getListTableIndexesSQL($table)
{
return "SELECT relname, pg_index.indisunique, pg_index.indisprimary,
pg_index.indkey, pg_index.indrelid
FROM pg_class, pg_index
WHERE oid IN (
SELECT indexrelid
FROM pg_index, pg_class
WHERE pg_class.relname='$table' AND pg_class.oid=pg_index.indrelid
) AND pg_index.indexrelid = oid";
}
public function getListTableColumnsSQL($table)
{
return "SELECT
a.attnum,
a.attname AS field,
t.typname AS type,
format_type(a.atttypid, a.atttypmod) AS complete_type,
(SELECT t1.typname FROM pg_catalog.pg_type t1 WHERE t1.oid = t.typbasetype) AS domain_type,
(SELECT format_type(t2.typbasetype, t2.typtypmod) FROM pg_catalog.pg_type t2
WHERE t2.typtype = 'd' AND t2.typname = format_type(a.atttypid, a.atttypmod)) AS domain_complete_type,
a.attnotnull AS isnotnull,
(SELECT 't'
FROM pg_index
WHERE c.oid = pg_index.indrelid
AND pg_index.indkey[0] = a.attnum
AND pg_index.indisprimary = 't'
) AS pri,
(SELECT pg_attrdef.adsrc
FROM pg_attrdef
WHERE c.oid = pg_attrdef.adrelid
AND pg_attrdef.adnum=a.attnum
) AS default
FROM pg_attribute a, pg_class c, pg_type t
WHERE c.relname = '$table'
AND a.attnum > 0
AND a.attrelid = c.oid
AND a.atttypid = t.oid
ORDER BY a.attnum";
}
/**
* create a new database
*
* @param string $name name of the database that should be created
* @throws PDOException
* @return void
* @override
*/
public function getCreateDatabaseSQL($name)
{
return 'CREATE DATABASE ' . $name;
}
/**
* drop an existing database
*
* @param string $name name of the database that should be dropped
* @throws PDOException
* @access public
*/
public function getDropDatabaseSQL($name)
{
return 'DROP DATABASE ' . $name;
}
/**
* Return the FOREIGN KEY query section dealing with non-standard options
* as MATCH, INITIALLY DEFERRED, ON UPDATE, ...
*
* @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey foreign key definition
* @return string
* @override
*/
public function getAdvancedForeignKeyOptionsSQL(\Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey)
{
$query = '';
if ($foreignKey->hasOption('match')) {
$query .= ' MATCH ' . $foreignKey->getOption('match');
}
$query .= parent::getAdvancedForeignKeyOptionsSQL($foreignKey);
if ($foreignKey->hasOption('deferrable') && $foreignKey->getOption('deferrable') !== false) {
$query .= ' DEFERRABLE';
} else {
$query .= ' NOT DEFERRABLE';
}
if ($foreignKey->hasOption('feferred') && $foreignKey->getOption('feferred') !== false) {
$query .= ' INITIALLY DEFERRED';
} else {
$query .= ' INITIALLY IMMEDIATE';
}
return $query;
}
/**
* generates the sql for altering an existing table on postgresql
*
* @param string $name name of the table that is intended to be changed.
* @param array $changes associative array that contains the details of each type *
* @param boolean $check indicates whether the function should just check if the DBMS driver
* can perform the requested table alterations if the value is true or
* actually perform them otherwise.
* @see Doctrine_Export::alterTable()
* @return array
* @override
*/
public function getAlterTableSQL(TableDiff $diff)
{
$sql = array();
foreach ($diff->addedColumns as $column) {
$query = 'ADD ' . $this->getColumnDeclarationSQL($column->getName(), $column->toArray());
$sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query;
}
foreach ($diff->removedColumns as $column) {
$query = 'DROP ' . $column->getName();
$sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query;
}
foreach ($diff->changedColumns AS $columnDiff) {
$oldColumnName = $columnDiff->oldColumnName;
$column = $columnDiff->column;
if ($columnDiff->hasChanged('type')) {
$type = $column->getType();
// here was a server version check before, but DBAL API does not support this anymore.
$query = 'ALTER ' . $oldColumnName . ' TYPE ' . $type->getSqlDeclaration($column->toArray(), $this);
$sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query;
}
if ($columnDiff->hasChanged('default')) {
$query = 'ALTER ' . $oldColumnName . ' SET ' . $this->getDefaultValueDeclarationSQL($column->toArray());
$sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query;
}
if ($columnDiff->hasChanged('notnull')) {
$query = 'ALTER ' . $oldColumnName . ' ' . ($column->getNotNull() ? 'SET' : 'DROP') . ' NOT NULL';
$sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query;
}
if ($columnDiff->hasChanged('autoincrement')) {
if ($column->getAutoincrement()) {
// add autoincrement
$seqName = $diff->name . '_' . $oldColumnName . '_seq';
$sql[] = "CREATE SEQUENCE " . $seqName;
$sql[] = "SELECT setval('" . $seqName . "', (SELECT MAX(" . $oldColumnName . ") FROM " . $diff->name . "))";
$query = "ALTER " . $oldColumnName . " SET DEFAULT nextval('" . $seqName . "')";
$sql[] = "ALTER TABLE " . $diff->name . " " . $query;
} else {
// Drop autoincrement, but do NOT drop the sequence. It might be re-used by other tables or have
$query = "ALTER " . $oldColumnName . " " . "DROP DEFAULT";
$sql[] = "ALTER TABLE " . $diff->name . " " . $query;
}
}
}
foreach ($diff->renamedColumns as $oldColumnName => $column) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' RENAME COLUMN ' . $oldColumnName . ' TO ' . $column->getName();
}
if ($diff->newName !== false) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' RENAME TO ' . $diff->newName;
}
$sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff));
return $sql;
}
/**
* Gets the SQL to create a sequence on this platform.
*
* @param \Doctrine\DBAL\Schema\Sequence $sequence
* @return string
*/
public function getCreateSequenceSQL(\Doctrine\DBAL\Schema\Sequence $sequence)
{
return 'CREATE SEQUENCE ' . $sequence->getName() .
' INCREMENT BY ' . $sequence->getAllocationSize() .
' MINVALUE ' . $sequence->getInitialValue() .
' START ' . $sequence->getInitialValue();
}
/**
* Drop existing sequence
* @param \Doctrine\DBAL\Schema\Sequence $sequence
* @return string
*/
public function getDropSequenceSQL($sequence)
{
if ($sequence instanceof \Doctrine\DBAL\Schema\Sequence) {
$sequence = $sequence->getName();
}
return 'DROP SEQUENCE ' . $sequence;
}
/**
* @param ForeignKeyConstraint|string $foreignKey
* @param Table|string $table
* @return string
*/
public function getDropForeignKeySQL($foreignKey, $table)
{
return $this->getDropConstraintSQL($foreignKey, $table);
}
/**
* Gets the SQL used to create a table.
*
* @param unknown_type $tableName
* @param array $columns
* @param array $options
* @return unknown
*/
protected function _getCreateTableSQL($tableName, array $columns, array $options = array())
{
$queryFields = $this->getColumnDeclarationListSQL($columns);
if (isset($options['primary']) && ! empty($options['primary'])) {
$keyColumns = array_unique(array_values($options['primary']));
$queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')';
}
$query = 'CREATE TABLE ' . $tableName . ' (' . $queryFields . ')';
$sql[] = $query;
if (isset($options['indexes']) && ! empty($options['indexes'])) {
foreach ($options['indexes'] AS $index) {
$sql[] = $this->getCreateIndexSQL($index, $tableName);
}
}
if (isset($options['foreignKeys'])) {
foreach ((array) $options['foreignKeys'] as $definition) {
$sql[] = $this->getCreateForeignKeySQL($definition, $tableName);
}
}
return $sql;
}
/**
* Postgres wants boolean values converted to the strings 'true'/'false'.
*
* @param array $item
* @override
*/
public function convertBooleans($item)
{
if (is_array($item)) {
foreach ($item as $key => $value) {
if (is_bool($value) || is_numeric($item)) {
$item[$key] = ($value) ? 'true' : 'false';
}
}
} else {
if (is_bool($item) || is_numeric($item)) {
$item = ($item) ? 'true' : 'false';
}
}
return $item;
}
public function getSequenceNextValSQL($sequenceName)
{
return "SELECT NEXTVAL('" . $sequenceName . "')";
}
public function getSetTransactionIsolationSQL($level)
{
return 'SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL '
. $this->_getTransactionIsolationLevelSQL($level);
}
/**
* @override
*/
public function getBooleanTypeDeclarationSQL(array $field)
{
return 'BOOLEAN';
}
/**
* @override
*/
public function getIntegerTypeDeclarationSQL(array $field)
{
if ( ! empty($field['autoincrement'])) {
return 'SERIAL';
}
return 'INT';
}
/**
* @override
*/
public function getBigIntTypeDeclarationSQL(array $field)
{
if ( ! empty($field['autoincrement'])) {
return 'BIGSERIAL';
}
return 'BIGINT';
}
/**
* @override
*/
public function getSmallIntTypeDeclarationSQL(array $field)
{
return 'SMALLINT';
}
/**
* @override
*/
public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
{
return 'TIMESTAMP(0) WITHOUT TIME ZONE';
}
/**
* @override
*/
public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration)
{
return 'TIMESTAMP(0) WITH TIME ZONE';
}
/**
* @override
*/
public function getDateTypeDeclarationSQL(array $fieldDeclaration)
{
return 'DATE';
}
/**
* @override
*/
public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
{
return 'TIME(0) WITHOUT TIME ZONE';
}
/**
* @override
*/
protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef)
{
return '';
}
/**
* Gets the SQL snippet used to declare a VARCHAR column on the MySql platform.
*
* @params array $field
* @override
*/
public function getVarcharTypeDeclarationSQL(array $field)
{
if ( ! isset($field['length'])) {
if (array_key_exists('default', $field)) {
$field['length'] = $this->getVarcharMaxLength();
} else {
$field['length'] = false;
}
}
$length = ($field['length'] <= $this->getVarcharMaxLength()) ? $field['length'] : false;
$fixed = (isset($field['fixed'])) ? $field['fixed'] : false;
return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)')
: ($length ? 'VARCHAR(' . $length . ')' : 'TEXT');
}
/** @override */
public function getClobTypeDeclarationSQL(array $field)
{
return 'TEXT';
}
/**
* Get the platform name for this instance
*
* @return string
*/
public function getName()
{
return 'postgresql';
}
/**
* Gets the character casing of a column in an SQL result set.
*
* PostgreSQL returns all column names in SQL result sets in lowercase.
*
* @param string $column The column name for which to get the correct character casing.
* @return string The column name in the character casing used in SQL result sets.
*/
public function getSQLResultCasing($column)
{
return strtolower($column);
}
public function getDateTimeTzFormatString()
{
return 'Y-m-d H:i:sO';
}
/**
* Get the insert sql for an empty insert statement
*
* @param string $tableName
* @param string $identifierColumnName
* @return string $sql
*/
public function getEmptyIdentityInsertSQL($quotedTableName, $quotedIdentifierColumnName)
{
return 'INSERT INTO ' . $quotedTableName . ' (' . $quotedIdentifierColumnName . ') VALUES (DEFAULT)';
}
/**
* @inheritdoc
*/
public function getTruncateTableSQL($tableName, $cascade = false)
{
return 'TRUNCATE '.$tableName.' '.($cascade)?'CASCADE':'';
}
public function getReadLockSQL()
{
return 'FOR SHARE';
}
protected function initializeDoctrineTypeMappings()
{
$this->doctrineTypeMapping = array(
'smallint' => 'smallint',
'int2' => 'smallint',
'serial' => 'integer',
'serial4' => 'integer',
'int' => 'integer',
'int4' => 'integer',
'integer' => 'integer',
'bigserial' => 'bigint',
'serial8' => 'bigint',
'bigint' => 'bigint',
'int8' => 'bigint',
'bool' => 'boolean',
'boolean' => 'boolean',
'text' => 'text',
'varchar' => 'string',
'interval' => 'string',
'_varchar' => 'string',
'char' => 'string',
'bpchar' => 'string',
'date' => 'date',
'datetime' => 'datetime',
'timestamp' => 'datetime',
'timestamptz' => 'datetimetz',
'time' => 'time',
'timetz' => 'time',
'float' => 'float',
'float4' => 'float',
'float8' => 'float',
'double' => 'float',
'double precision' => 'float',
'real' => 'float',
'decimal' => 'decimal',
'money' => 'decimal',
'numeric' => 'decimal',
'year' => 'date',
);
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms;
use Doctrine\DBAL\Schema\TableDiff;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Schema\Index, Doctrine\DBAL\Schema\Table;
/**
* The MsSqlPlatform provides the behavior, features and SQL dialect of the
* MySQL database platform.
*
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
* @author Jonathan H. Wage <jonwage@gmail.com>
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @todo Rename: MsSQLPlatform
*/
class MsSqlPlatform extends AbstractPlatform
{
/**
* Whether the platform prefers identity columns for ID generation.
* MsSql prefers "autoincrement" identity columns since sequences can only
* be emulated with a table.
*
* @return boolean
* @override
*/
public function prefersIdentityColumns()
{
return true;
}
/**
* Whether the platform supports identity columns.
* MsSql supports this through AUTO_INCREMENT columns.
*
* @return boolean
* @override
*/
public function supportsIdentityColumns()
{
return true;
}
/**
* Whether the platform supports releasing savepoints.
*
* @return boolean
*/
public function supportsReleaseSavepoints()
{
return false;
}
/**
* create a new database
*
* @param string $name name of the database that should be created
* @return string
* @override
*/
public function getCreateDatabaseSQL($name)
{
return 'CREATE DATABASE ' . $name;
}
/**
* drop an existing database
*
* @param string $name name of the database that should be dropped
* @return string
* @override
*/
public function getDropDatabaseSQL($name)
{
// @todo do we really need to force drop?
return 'ALTER DATABASE [' . $name . ']
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE;
DROP DATABASE ' . $name . ';';
}
/**
* @override
*/
public function quoteIdentifier($str)
{
return '[' . $str . ']';
}
/**
* @override
*/
public function getDropForeignKeySQL($foreignKey, $table)
{
if ($foreignKey instanceof \Doctrine\DBAL\Schema\ForeignKeyConstraint) {
$foreignKey = $foreignKey->getName();
}
if ($table instanceof \Doctrine\DBAL\Schema\Table) {
$table = $table->getName();
}
return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $foreignKey;
}
/**
* @override
*/
public function getDropIndexSQL($index, $table=null)
{
if ($index instanceof \Doctrine\DBAL\Schema\Index) {
$index_ = $index;
$index = $index->getName();
} else if (!is_string($index)) {
throw new \InvalidArgumentException('AbstractPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.');
}
if (!isset($table)) {
return 'DROP INDEX ' . $index;
} else {
if ($table instanceof \Doctrine\DBAL\Schema\Table) {
$table = $table->getName();
}
return "IF EXISTS (SELECT * FROM sysobjects WHERE name = '$index')
ALTER TABLE " . $this->quoteIdentifier($table) . " DROP CONSTRAINT " . $this->quoteIdentifier($index) . "
ELSE
DROP INDEX " . $this->quoteIdentifier($index) . " ON " . $this->quoteIdentifier($table);
}
}
/**
* @override
*/
public function getCreateTableSQL(Table $table, $createFlags=self::CREATE_INDEXES)
{
$sql = parent::getCreateTableSQL($table, $createFlags);
$primary = array();
foreach ($table->getIndexes() AS $index) {
/* @var $index Index */
if ($index->isPrimary()) {
$primary = $index->getColumns();
}
}
if (count($primary) === 1) {
foreach ($table->getForeignKeys() AS $definition) {
$columns = $definition->getLocalColumns();
if (count($columns) === 1 && in_array($columns[0], $primary)) {
$sql[0] = str_replace(' IDENTITY', '', $sql[0]);
}
}
}
return $sql;
}
/**
* @override
*/
protected function _getCreateTableSQL($tableName, array $columns, array $options = array())
{
$columnListSql = $this->getColumnDeclarationListSQL($columns);
if (isset($options['uniqueConstraints']) && !empty($options['uniqueConstraints'])) {
foreach ($options['uniqueConstraints'] as $name => $definition) {
$columnListSql .= ', ' . $this->getUniqueConstraintDeclarationSQL($name, $definition);
}
}
if (isset($options['primary']) && !empty($options['primary'])) {
$columnListSql .= ', PRIMARY KEY(' . implode(', ', array_unique(array_values($options['primary']))) . ')';
}
$query = 'CREATE TABLE ' . $tableName . ' (' . $columnListSql;
$check = $this->getCheckDeclarationSQL($columns);
if (!empty($check)) {
$query .= ', ' . $check;
}
$query .= ')';
$sql[] = $query;
if (isset($options['indexes']) && !empty($options['indexes'])) {
foreach ($options['indexes'] AS $index) {
$sql[] = $this->getCreateIndexSQL($index, $tableName);
}
}
if (isset($options['foreignKeys'])) {
foreach ((array) $options['foreignKeys'] AS $definition) {
$sql[] = $this->getCreateForeignKeySQL($definition, $tableName);
}
}
return $sql;
}
/**
* @override
*/
public function getAlterTableSQL(TableDiff $diff)
{
$queryParts = array();
if ($diff->newName !== false) {
$queryParts[] = 'RENAME TO ' . $diff->newName;
}
foreach ($diff->addedColumns AS $fieldName => $column) {
$queryParts[] = 'ADD ' . $this->getColumnDeclarationSQL($column->getName(), $column->toArray());
}
foreach ($diff->removedColumns AS $column) {
$queryParts[] = 'DROP COLUMN ' . $column->getName();
}
foreach ($diff->changedColumns AS $columnDiff) {
/* @var $columnDiff Doctrine\DBAL\Schema\ColumnDiff */
$column = $columnDiff->column;
$queryParts[] = 'CHANGE ' . ($columnDiff->oldColumnName) . ' '
. $this->getColumnDeclarationSQL($column->getName(), $column->toArray());
}
foreach ($diff->renamedColumns AS $oldColumnName => $column) {
$queryParts[] = 'CHANGE ' . $oldColumnName . ' '
. $this->getColumnDeclarationSQL($column->getName(), $column->toArray());
}
$sql = array();
foreach ($queryParts as $query) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query;
}
$sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff));
return $sql;
}
/**
* @override
*/
public function getEmptyIdentityInsertSQL($quotedTableName, $quotedIdentifierColumnName)
{
return 'INSERT INTO ' . $quotedTableName . ' DEFAULT VALUES';
}
/**
* @override
*/
public function getShowDatabasesSQL()
{
return 'SHOW DATABASES';
}
/**
* @override
*/
public function getListTablesSQL()
{
return "SELECT name FROM sysobjects WHERE type = 'U' ORDER BY name";
}
/**
* @override
*/
public function getListTableColumnsSQL($table)
{
return 'exec sp_columns @table_name = ' . $table;
}
/**
* @override
*/
public function getListTableForeignKeysSQL($table, $database = null)
{
return "SELECT f.name AS ForeignKey,
SCHEMA_NAME (f.SCHEMA_ID) AS SchemaName,
OBJECT_NAME (f.parent_object_id) AS TableName,
COL_NAME (fc.parent_object_id,fc.parent_column_id) AS ColumnName,
SCHEMA_NAME (o.SCHEMA_ID) ReferenceSchemaName,
OBJECT_NAME (f.referenced_object_id) AS ReferenceTableName,
COL_NAME(fc.referenced_object_id,fc.referenced_column_id) AS ReferenceColumnName,
f.delete_referential_action_desc,
f.update_referential_action_desc
FROM sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS fc
INNER JOIN sys.objects AS o ON o.OBJECT_ID = fc.referenced_object_id
ON f.OBJECT_ID = fc.constraint_object_id
WHERE OBJECT_NAME (f.parent_object_id) = '" . $table . "'";
}
/**
* @override
*/
public function getListTableIndexesSQL($table)
{
return "exec sp_helpindex '" . $table . "'";
}
/**
* @override
*/
public function getCreateViewSQL($name, $sql)
{
return 'CREATE VIEW ' . $name . ' AS ' . $sql;
}
/**
* @override
*/
public function getListViewsSQL($database)
{
return "SELECT name FROM sysobjects WHERE type = 'V' ORDER BY name";
}
/**
* @override
*/
public function getDropViewSQL($name)
{
return 'DROP VIEW ' . $name;
}
/**
* Returns the regular expression operator.
*
* @return string
* @override
*/
public function getRegexpExpression()
{
return 'RLIKE';
}
/**
* Returns global unique identifier
*
* @return string to get global unique identifier
* @override
*/
public function getGuidExpression()
{
return 'UUID()';
}
/**
* @override
*/
public function getLocateExpression($str, $substr, $startPos = false)
{
if ($startPos == false) {
return 'CHARINDEX(' . $substr . ', ' . $str . ')';
} else {
return 'CHARINDEX(' . $substr . ', ' . $str . ', ' . $startPos . ')';
}
}
/**
* @override
*/
public function getModExpression($expression1, $expression2)
{
return $expression1 . ' % ' . $expression2;
}
/**
* @override
*/
public function getTrimExpression($str, $pos = self::TRIM_UNSPECIFIED, $char = false)
{
// @todo
$trimFn = '';
$trimChar = ($char != false) ? (', ' . $char) : '';
if ($pos == self::TRIM_LEADING) {
$trimFn = 'LTRIM';
} else if ($pos == self::TRIM_TRAILING) {
$trimFn = 'RTRIM';
} else {
return 'LTRIM(RTRIM(' . $str . '))';
}
return $trimFn . '(' . $str . ')';
}
/**
* @override
*/
public function getConcatExpression()
{
$args = func_get_args();
return '(' . implode(' + ', $args) . ')';
}
public function getListDatabasesSQL()
{
return 'SELECT * FROM SYS.DATABASES';
}
/**
* @override
*/
public function getSubstringExpression($value, $from, $len = null)
{
if (!is_null($len)) {
return 'SUBSTRING(' . $value . ', ' . $from . ', ' . $len . ')';
}
return 'SUBSTRING(' . $value . ', ' . $from . ', LEN(' . $value . ') - ' . $from . ' + 1)';
}
/**
* @override
*/
public function getLengthExpression($column)
{
return 'LEN(' . $column . ')';
}
/**
* @override
*/
public function getSetTransactionIsolationSQL($level)
{
return 'SET TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level);
}
/**
* @override
*/
public function getIntegerTypeDeclarationSQL(array $field)
{
return 'INT' . $this->_getCommonIntegerTypeDeclarationSQL($field);
}
/**
* @override
*/
public function getBigIntTypeDeclarationSQL(array $field)
{
return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($field);
}
/**
* @override
*/
public function getSmallIntTypeDeclarationSQL(array $field)
{
return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($field);
}
/** @override */
public function getVarcharTypeDeclarationSQL(array $field)
{
if (!isset($field['length'])) {
if (array_key_exists('default', $field)) {
$field['length'] = $this->getVarcharMaxLength();
} else {
$field['length'] = false;
}
}
$length = ($field['length'] <= $this->getVarcharMaxLength()) ? $field['length'] : false;
$fixed = (isset($field['fixed'])) ? $field['fixed'] : false;
return $fixed ? ($length ? 'NCHAR(' . $length . ')' : 'CHAR(255)') : ($length ? 'NVARCHAR(' . $length . ')' : 'NTEXT');
}
/** @override */
public function getClobTypeDeclarationSQL(array $field)
{
return 'TEXT';
}
/**
* @override
*/
protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef)
{
$autoinc = '';
if (!empty($columnDef['autoincrement'])) {
$autoinc = ' IDENTITY';
}
$unsigned = (isset($columnDef['unsigned']) && $columnDef['unsigned']) ? ' UNSIGNED' : '';
return $unsigned . $autoinc;
}
/**
* @override
*/
public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
{
// 6 - microseconds precision length
return 'DATETIME2(6)';
}
/**
* @override
*/
public function getDateTypeDeclarationSQL(array $fieldDeclaration)
{
return 'DATE';
}
/**
* @override
*/
public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
{
return 'TIME(0)';
}
/**
* @override
*/
public function getBooleanTypeDeclarationSQL(array $field)
{
return 'BIT';
}
/**
* Adds an adapter-specific LIMIT clause to the SELECT statement.
*
* @param string $query
* @param mixed $limit
* @param mixed $offset
* @link http://lists.bestpractical.com/pipermail/rt-devel/2005-June/007339.html
* @return string
*/
public function modifyLimitQuery($query, $limit, $offset = null)
{
if ($limit > 0) {
$count = intval($limit);
$offset = intval($offset);
if ($offset < 0) {
throw new Doctrine_Connection_Exception("LIMIT argument offset=$offset is not valid");
}
if ($offset == 0) {
$query = preg_replace('/^SELECT\s/i', 'SELECT TOP ' . $count . ' ', $query);
} else {
$orderby = stristr($query, 'ORDER BY');
if (!$orderby) {
$over = 'ORDER BY (SELECT 0)';
} else {
$over = preg_replace('/\"[^,]*\".\"([^,]*)\"/i', '"inner_tbl"."$1"', $orderby);
}
// Remove ORDER BY clause from $query
$query = preg_replace('/\s+ORDER BY(.*)/', '', $query);
// Add ORDER BY clause as an argument for ROW_NUMBER()
$query = "SELECT ROW_NUMBER() OVER ($over) AS \"doctrine_rownum\", * FROM ($query) AS inner_tbl";
$start = $offset + 1;
$end = $offset + $count;
$query = "WITH outer_tbl AS ($query) SELECT * FROM outer_tbl WHERE \"doctrine_rownum\" BETWEEN $start AND $end";
}
}
return $query;
}
/**
* @override
*/
public function convertBooleans($item)
{
if (is_array($item)) {
foreach ($item as $key => $value) {
if (is_bool($value) || is_numeric($item)) {
$item[$key] = ($value) ? 'TRUE' : 'FALSE';
}
}
} else {
if (is_bool($item) || is_numeric($item)) {
$item = ($item) ? 'TRUE' : 'FALSE';
}
}
return $item;
}
/**
* @override
*/
public function getCreateTemporaryTableSnippetSQL()
{
return "CREATE TABLE";
}
/**
* @override
*/
public function getTemporaryTableName($tableName)
{
return '#' . $tableName;
}
/**
* @override
*/
public function getDateTimeFormatString()
{
return 'Y-m-d H:i:s.u';
}
/**
* @override
*/
public function getDateTimeTzFormatString()
{
return $this->getDateTimeFormatString();
}
/**
* Get the platform name for this instance
*
* @return string
*/
public function getName()
{
return 'mssql';
}
protected function initializeDoctrineTypeMappings()
{
$this->doctrineTypeMapping = array(
'bigint' => 'bigint',
'numeric' => 'decimal',
'bit' => 'boolean',
'smallint' => 'smallint',
'decimal' => 'decimal',
'smallmoney' => 'integer',
'int' => 'integer',
'tinyint' => 'smallint',
'money' => 'integer',
'float' => 'float',
'real' => 'float',
'double' => 'float',
'double precision' => 'float',
'date' => 'date',
'datetimeoffset' => 'datetimetz',
'datetime2' => 'datetime',
'smalldatetime' => 'datetime',
'datetime' => 'datetime',
'time' => 'time',
'char' => 'string',
'varchar' => 'string',
'text' => 'text',
'nchar' => 'string',
'nvarchar' => 'string',
'ntext' => 'text',
'binary' => 'text',
'varbinary' => 'text',
'image' => 'text',
);
}
/**
* Generate SQL to create a new savepoint
*
* @param string $savepoint
* @return string
*/
public function createSavePoint($savepoint)
{
return 'SAVE TRANSACTION ' . $savepoint;
}
/**
* Generate SQL to release a savepoint
*
* @param string $savepoint
* @return string
*/
public function releaseSavePoint($savepoint)
{
return '';
}
/**
* Generate SQL to rollback a savepoint
*
* @param string $savepoint
* @return string
*/
public function rollbackSavePoint($savepoint)
{
return 'ROLLBACK TRANSACTION ' . $savepoint;
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms;
use Doctrine\DBAL\Schema\TableDiff;
/**
* OraclePlatform.
*
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class OraclePlatform extends AbstractPlatform
{
/**
* return string to call a function to get a substring inside an SQL statement
*
* Note: Not SQL92, but common functionality.
*
* @param string $value an sql string literal or column name/alias
* @param integer $position where to start the substring portion
* @param integer $length the substring portion length
* @return string SQL substring function with given parameters
* @override
*/
public function getSubstringExpression($value, $position, $length = null)
{
if ($length !== null) {
return "SUBSTR($value, $position, $length)";
}
return "SUBSTR($value, $position)";
}
/**
* Return string to call a variable with the current timestamp inside an SQL statement
* There are three special variables for current date and time:
* - CURRENT_TIMESTAMP (date and time, TIMESTAMP type)
* - CURRENT_DATE (date, DATE type)
* - CURRENT_TIME (time, TIME type)
*
* @return string to call a variable with the current timestamp
* @override
*/
public function getNowExpression($type = 'timestamp')
{
switch ($type) {
case 'date':
case 'time':
case 'timestamp':
default:
return 'TO_CHAR(CURRENT_TIMESTAMP, \'YYYY-MM-DD HH24:MI:SS\')';
}
}
/**
* returns the position of the first occurrence of substring $substr in string $str
*
* @param string $substr literal string to find
* @param string $str literal string
* @param int $pos position to start at, beginning of string by default
* @return integer
*/
public function getLocateExpression($str, $substr, $startPos = false)
{
if ($startPos == false) {
return 'INSTR('.$str.', '.$substr.')';
} else {
return 'INSTR('.$str.', '.$substr.', '.$startPos.')';
}
}
/**
* Returns global unique identifier
*
* @return string to get global unique identifier
* @override
*/
public function getGuidExpression()
{
return 'SYS_GUID()';
}
/**
* Gets the SQL used to create a sequence that starts with a given value
* and increments by the given allocation size.
*
* Need to specifiy minvalue, since start with is hidden in the system and MINVALUE <= START WITH.
* Therefore we can use MINVALUE to be able to get a hint what START WITH was for later introspection
* in {@see listSequences()}
*
* @param \Doctrine\DBAL\Schema\Sequence $sequence
* @return string
*/
public function getCreateSequenceSQL(\Doctrine\DBAL\Schema\Sequence $sequence)
{
return 'CREATE SEQUENCE ' . $sequence->getName() .
' START WITH ' . $sequence->getInitialValue() .
' MINVALUE ' . $sequence->getInitialValue() .
' INCREMENT BY ' . $sequence->getAllocationSize();
}
/**
* {@inheritdoc}
*
* @param string $sequenceName
* @override
*/
public function getSequenceNextValSQL($sequenceName)
{
return 'SELECT ' . $sequenceName . '.nextval FROM DUAL';
}
/**
* {@inheritdoc}
*
* @param integer $level
* @override
*/
public function getSetTransactionIsolationSQL($level)
{
return 'SET TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level);
}
protected function _getTransactionIsolationLevelSQL($level)
{
switch ($level) {
case \Doctrine\DBAL\Connection::TRANSACTION_READ_UNCOMMITTED:
return 'READ UNCOMMITTED';
case \Doctrine\DBAL\Connection::TRANSACTION_READ_COMMITTED:
return 'READ COMMITTED';
case \Doctrine\DBAL\Connection::TRANSACTION_REPEATABLE_READ:
case \Doctrine\DBAL\Connection::TRANSACTION_SERIALIZABLE:
return 'SERIALIZABLE';
default:
return parent::_getTransactionIsolationLevelSQL($level);
}
}
/**
* @override
*/
public function getBooleanTypeDeclarationSQL(array $field)
{
return 'NUMBER(1)';
}
/**
* @override
*/
public function getIntegerTypeDeclarationSQL(array $field)
{
return 'NUMBER(10)';
}
/**
* @override
*/
public function getBigIntTypeDeclarationSQL(array $field)
{
return 'NUMBER(20)';
}
/**
* @override
*/
public function getSmallIntTypeDeclarationSQL(array $field)
{
return 'NUMBER(5)';
}
/**
* @override
*/
public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
{
return 'TIMESTAMP(0)';
}
/**
* @override
*/
public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration)
{
return 'TIMESTAMP(0) WITH TIME ZONE';
}
/**
* @override
*/
public function getDateTypeDeclarationSQL(array $fieldDeclaration)
{
return 'DATE';
}
/**
* @override
*/
public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
{
return 'DATE';
}
/**
* @override
*/
protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef)
{
return '';
}
/**
* Gets the SQL snippet used to declare a VARCHAR column on the Oracle platform.
*
* @params array $field
* @override
*/
public function getVarcharTypeDeclarationSQL(array $field)
{
if ( ! isset($field['length'])) {
if (array_key_exists('default', $field)) {
$field['length'] = $this->getVarcharMaxLength();
} else {
$field['length'] = false;
}
}
$length = ($field['length'] <= $this->getVarcharMaxLength()) ? $field['length'] : false;
$fixed = (isset($field['fixed'])) ? $field['fixed'] : false;
return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(2000)')
: ($length ? 'VARCHAR2(' . $length . ')' : 'VARCHAR2(4000)');
}
/** @override */
public function getClobTypeDeclarationSQL(array $field)
{
return 'CLOB';
}
public function getListDatabasesSQL()
{
return 'SELECT username FROM all_users';
}
public function getListSequencesSQL($database)
{
return "SELECT sequence_name, min_value, increment_by FROM sys.all_sequences ".
"WHERE SEQUENCE_OWNER = '".strtoupper($database)."'";
}
/**
*
* @param string $table
* @param array $columns
* @param array $options
* @return array
*/
protected function _getCreateTableSQL($table, array $columns, array $options = array())
{
$indexes = isset($options['indexes']) ? $options['indexes'] : array();
$options['indexes'] = array();
$sql = parent::_getCreateTableSQL($table, $columns, $options);
foreach ($columns as $name => $column) {
if (isset($column['sequence'])) {
$sql[] = $this->getCreateSequenceSQL($column['sequence'], 1);
}
if (isset($column['autoincrement']) && $column['autoincrement'] ||
(isset($column['autoinc']) && $column['autoinc'])) {
$sql = array_merge($sql, $this->getCreateAutoincrementSql($name, $table));
}
}
if (isset($indexes) && ! empty($indexes)) {
foreach ($indexes as $indexName => $index) {
$sql[] = $this->getCreateIndexSQL($index, $table);
}
}
return $sql;
}
/**
* @license New BSD License
* @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaOracleReader.html
* @param string $table
* @return string
*/
public function getListTableIndexesSQL($table)
{
$table = strtoupper($table);
return "SELECT uind.index_name AS name, " .
" uind.index_type AS type, " .
" decode( uind.uniqueness, 'NONUNIQUE', 0, 'UNIQUE', 1 ) AS is_unique, " .
" uind_col.column_name AS column_name, " .
" uind_col.column_position AS column_pos, " .
" (SELECT ucon.constraint_type FROM user_constraints ucon WHERE ucon.constraint_name = uind.index_name) AS is_primary ".
"FROM user_indexes uind, user_ind_columns uind_col " .
"WHERE uind.index_name = uind_col.index_name AND uind_col.table_name = '$table' ORDER BY uind_col.column_position ASC";
}
public function getListTablesSQL()
{
return 'SELECT * FROM sys.user_tables';
}
public function getListViewsSQL($database)
{
return 'SELECT view_name, text FROM sys.user_views';
}
public function getCreateViewSQL($name, $sql)
{
return 'CREATE VIEW ' . $name . ' AS ' . $sql;
}
public function getDropViewSQL($name)
{
return 'DROP VIEW '. $name;
}
public function getCreateAutoincrementSql($name, $table, $start = 1)
{
$table = strtoupper($table);
$sql = array();
$indexName = $table . '_AI_PK';
$definition = array(
'primary' => true,
'columns' => array($name => true),
);
$idx = new \Doctrine\DBAL\Schema\Index($indexName, array($name), true, true);
$sql[] = 'DECLARE
constraints_Count NUMBER;
BEGIN
SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = \''.$table.'\' AND CONSTRAINT_TYPE = \'P\';
IF constraints_Count = 0 OR constraints_Count = \'\' THEN
EXECUTE IMMEDIATE \''.$this->getCreateConstraintSQL($idx, $table).'\';
END IF;
END;';
$sequenceName = $table . '_SEQ';
$sequence = new \Doctrine\DBAL\Schema\Sequence($sequenceName, $start);
$sql[] = $this->getCreateSequenceSQL($sequence);
$triggerName = $table . '_AI_PK';
$sql[] = 'CREATE TRIGGER ' . $triggerName . '
BEFORE INSERT
ON ' . $table . '
FOR EACH ROW
DECLARE
last_Sequence NUMBER;
last_InsertID NUMBER;
BEGIN
SELECT ' . $sequenceName . '.NEXTVAL INTO :NEW.' . $name . ' FROM DUAL;
IF (:NEW.' . $name . ' IS NULL OR :NEW.'.$name.' = 0) THEN
SELECT ' . $sequenceName . '.NEXTVAL INTO :NEW.' . $name . ' FROM DUAL;
ELSE
SELECT NVL(Last_Number, 0) INTO last_Sequence
FROM User_Sequences
WHERE Sequence_Name = \'' . $sequenceName . '\';
SELECT :NEW.' . $name . ' INTO last_InsertID FROM DUAL;
WHILE (last_InsertID > last_Sequence) LOOP
SELECT ' . $sequenceName . '.NEXTVAL INTO last_Sequence FROM DUAL;
END LOOP;
END IF;
END;';
return $sql;
}
public function getDropAutoincrementSql($table)
{
$table = strtoupper($table);
$trigger = $table . '_AI_PK';
if ($trigger) {
$sql[] = 'DROP TRIGGER ' . $trigger;
$sql[] = $this->getDropSequenceSQL($table.'_SEQ');
$indexName = $table . '_AI_PK';
$sql[] = $this->getDropConstraintSQL($indexName, $table);
}
return $sql;
}
public function getListTableForeignKeysSQL($table)
{
$table = strtoupper($table);
return "SELECT alc.constraint_name,
alc.DELETE_RULE,
alc.search_condition,
cols.column_name \"local_column\",
cols.position,
r_alc.table_name \"references_table\",
r_cols.column_name \"foreign_column\"
FROM all_cons_columns cols
LEFT JOIN all_constraints alc
ON alc.constraint_name = cols.constraint_name
AND alc.owner = cols.owner
LEFT JOIN all_constraints r_alc
ON alc.r_constraint_name = r_alc.constraint_name
AND alc.r_owner = r_alc.owner
LEFT JOIN all_cons_columns r_cols
ON r_alc.constraint_name = r_cols.constraint_name
AND r_alc.owner = r_cols.owner
AND cols.position = r_cols.position
WHERE alc.constraint_name = cols.constraint_name
AND alc.constraint_type = 'R'
AND alc.table_name = '".$table."'";
}
public function getListTableConstraintsSQL($table)
{
$table = strtoupper($table);
return 'SELECT * FROM user_constraints WHERE table_name = \'' . $table . '\'';
}
public function getListTableColumnsSQL($table)
{
$table = strtoupper($table);
return "SELECT * FROM all_tab_columns WHERE table_name = '" . $table . "' ORDER BY column_name";
}
/**
*
* @param \Doctrine\DBAL\Schema\Sequence $sequence
* @return string
*/
public function getDropSequenceSQL($sequence)
{
if ($sequence instanceof \Doctrine\DBAL\Schema\Sequence) {
$sequence = $sequence->getName();
}
return 'DROP SEQUENCE ' . $sequence;
}
/**
* @param ForeignKeyConstraint|string $foreignKey
* @param Table|string $table
* @return string
*/
public function getDropForeignKeySQL($foreignKey, $table)
{
if ($foreignKey instanceof \Doctrine\DBAL\Schema\ForeignKeyConstraint) {
$foreignKey = $foreignKey->getName();
}
if ($table instanceof \Doctrine\DBAL\Schema\Table) {
$table = $table->getName();
}
return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $foreignKey;
}
public function getDropDatabaseSQL($database)
{
return 'DROP USER ' . $database . ' CASCADE';
}
/**
* Gets the sql statements for altering an existing table.
*
* The method returns an array of sql statements, since some platforms need several statements.
*
* @param string $diff->name name of the table that is intended to be changed.
* @param array $changes associative array that contains the details of each type *
* @param boolean $check indicates whether the function should just check if the DBMS driver
* can perform the requested table alterations if the value is true or
* actually perform them otherwise.
* @return array
*/
public function getAlterTableSQL(TableDiff $diff)
{
$sql = array();
$fields = array();
foreach ($diff->addedColumns AS $column) {
$fields[] = $this->getColumnDeclarationSQL($column->getName(), $column->toArray());
}
if (count($fields)) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' ADD (' . implode(', ', $fields) . ')';
}
$fields = array();
foreach ($diff->changedColumns AS $columnDiff) {
$column = $columnDiff->column;
$fields[] = $column->getName(). ' ' . $this->getColumnDeclarationSQL('', $column->toArray());
}
if (count($fields)) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' MODIFY (' . implode(', ', $fields) . ')';
}
foreach ($diff->renamedColumns AS $oldColumnName => $column) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' RENAME COLUMN ' . $oldColumnName .' TO ' . $column->getName();
}
$fields = array();
foreach ($diff->removedColumns AS $column) {
$fields[] = $column->getName();
}
if (count($fields)) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' DROP COLUMN ' . implode(', ', $fields);
}
if ($diff->newName !== false) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' RENAME TO ' . $diff->newName;
}
$sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff));
return $sql;
}
/**
* Whether the platform prefers sequences for ID generation.
*
* @return boolean
*/
public function prefersSequences()
{
return true;
}
/**
* Get the platform name for this instance
*
* @return string
*/
public function getName()
{
return 'oracle';
}
/**
* Adds an driver-specific LIMIT clause to the query
*
* @param string $query query to modify
* @param integer $limit limit the number of rows
* @param integer $offset start reading from given offset
* @return string the modified query
*/
public function modifyLimitQuery($query, $limit, $offset = null)
{
$limit = (int) $limit;
$offset = (int) $offset;
if (preg_match('/^\s*SELECT/i', $query)) {
if ( ! preg_match('/\sFROM\s/i', $query)) {
$query .= " FROM dual";
}
if ($limit > 0) {
$max = $offset + $limit;
$column = '*';
if ($offset > 0) {
$min = $offset + 1;
$query = 'SELECT b.'.$column.' FROM ('.
'SELECT a.*, ROWNUM AS doctrine_rownum FROM ('
. $query . ') a '.
') b '.
'WHERE doctrine_rownum BETWEEN ' . $min . ' AND ' . $max;
} else {
$query = 'SELECT a.'.$column.' FROM (' . $query .') a WHERE ROWNUM <= ' . $max;
}
}
}
return $query;
}
/**
* Gets the character casing of a column in an SQL result set of this platform.
*
* Oracle returns all column names in SQL result sets in uppercase.
*
* @param string $column The column name for which to get the correct character casing.
* @return string The column name in the character casing used in SQL result sets.
*/
public function getSQLResultCasing($column)
{
return strtoupper($column);
}
public function getCreateTemporaryTableSnippetSQL()
{
return "CREATE GLOBAL TEMPORARY TABLE";
}
public function getDateTimeTzFormatString()
{
return 'Y-m-d H:i:sP';
}
public function getDateFormatString()
{
return 'Y-m-d 00:00:00';
}
public function getTimeFormatString()
{
return '1900-01-01 H:i:s';
}
public function fixSchemaElementName($schemaElementName)
{
if (strlen($schemaElementName) > 30) {
// Trim it
return substr($schemaElementName, 0, 30);
}
return $schemaElementName;
}
/**
* Maximum length of any given databse identifier, like tables or column names.
*
* @return int
*/
public function getMaxIdentifierLength()
{
return 30;
}
/**
* Whether the platform supports sequences.
*
* @return boolean
*/
public function supportsSequences()
{
return true;
}
public function supportsForeignKeyOnUpdate()
{
return false;
}
/**
* Whether the platform supports releasing savepoints.
*
* @return boolean
*/
public function supportsReleaseSavepoints()
{
return false;
}
/**
* @inheritdoc
*/
public function getTruncateTableSQL($tableName, $cascade = false)
{
return 'TRUNCATE TABLE '.$tableName;
}
/**
* This is for test reasons, many vendors have special requirements for dummy statements.
*
* @return string
*/
public function getDummySelectSQL()
{
return 'SELECT 1 FROM DUAL';
}
protected function initializeDoctrineTypeMappings()
{
$this->doctrineTypeMapping = array(
'integer' => 'integer',
'number' => 'integer',
'pls_integer' => 'boolean',
'binary_integer' => 'boolean',
'varchar' => 'string',
'varchar2' => 'string',
'nvarchar2' => 'string',
'char' => 'string',
'nchar' => 'string',
'date' => 'datetime',
'timestamp' => 'datetime',
'timestamptz' => 'datetimetz',
'float' => 'float',
'long' => 'string',
'clob' => 'text',
'nclob' => 'text',
'rowid' => 'string',
'urowid' => 'string'
);
}
/**
* Generate SQL to release a savepoint
*
* @param string $savepoint
* @return string
*/
public function releaseSavePoint($savepoint)
{
return '';
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Schema\Index;
use Doctrine\DBAL\Schema\TableDiff;
class DB2Platform extends AbstractPlatform
{
public function initializeDoctrineTypeMappings()
{
$this->doctrineTypeMapping = array(
'smallint' => 'smallint',
'bigint' => 'bigint',
'integer' => 'integer',
'time' => 'time',
'date' => 'date',
'varchar' => 'string',
'character' => 'string',
'clob' => 'text',
'decimal' => 'decimal',
'double' => 'decimal',
'real' => 'decimal',
'timestamp' => 'datetime',
);
}
/**
* Gets the SQL snippet used to declare a VARCHAR column type.
*
* @param array $field
*/
public function getVarcharTypeDeclarationSQL(array $field)
{
if ( ! isset($field['length'])) {
if (array_key_exists('default', $field)) {
$field['length'] = $this->getVarcharMaxLength();
} else {
$field['length'] = false;
}
}
$length = ($field['length'] <= $this->getVarcharMaxLength()) ? $field['length'] : false;
$fixed = (isset($field['fixed'])) ? $field['fixed'] : false;
return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)')
: ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)');
}
/**
* Gets the SQL snippet used to declare a CLOB column type.
*
* @param array $field
*/
public function getClobTypeDeclarationSQL(array $field)
{
// todo clob(n) with $field['length'];
return 'CLOB(1M)';
}
/**
* Gets the name of the platform.
*
* @return string
*/
public function getName()
{
return 'db2';
}
/**
* Gets the SQL snippet that declares a boolean column.
*
* @param array $columnDef
* @return string
*/
public function getBooleanTypeDeclarationSQL(array $columnDef)
{
return 'SMALLINT';
}
/**
* Gets the SQL snippet that declares a 4 byte integer column.
*
* @param array $columnDef
* @return string
*/
public function getIntegerTypeDeclarationSQL(array $columnDef)
{
return 'INTEGER' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef);
}
/**
* Gets the SQL snippet that declares an 8 byte integer column.
*
* @param array $columnDef
* @return string
*/
public function getBigIntTypeDeclarationSQL(array $columnDef)
{
return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef);
}
/**
* Gets the SQL snippet that declares a 2 byte integer column.
*
* @param array $columnDef
* @return string
*/
public function getSmallIntTypeDeclarationSQL(array $columnDef)
{
return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef);
}
/**
* Gets the SQL snippet that declares common properties of an integer column.
*
* @param array $columnDef
* @return string
*/
protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef)
{
$autoinc = '';
if ( ! empty($columnDef['autoincrement'])) {
$autoinc = ' GENERATED BY DEFAULT AS IDENTITY';
}
return $autoinc;
}
/**
* Obtain DBMS specific SQL to be used to create datetime fields in
* statements like CREATE TABLE
*
* @param array $fieldDeclaration
* @return string
*/
public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
{
if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] == true) {
return "TIMESTAMP(0) WITH DEFAULT";
}
return 'TIMESTAMP(0)';
}
/**
* Obtain DBMS specific SQL to be used to create date fields in statements
* like CREATE TABLE.
*
* @param array $fieldDeclaration
* @return string
*/
public function getDateTypeDeclarationSQL(array $fieldDeclaration)
{
return 'DATE';
}
/**
* Obtain DBMS specific SQL to be used to create time fields in statements
* like CREATE TABLE.
*
* @param array $fieldDeclaration
* @return string
*/
public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
{
return 'TIME';
}
public function getListDatabasesSQL()
{
throw DBALException::notSupported(__METHOD__);
}
public function getListSequencesSQL($database)
{
throw DBALException::notSupported(__METHOD__);
}
public function getListTableConstraintsSQL($table)
{
throw DBALException::notSupported(__METHOD__);
}
/**
* This code fragment is originally from the Zend_Db_Adapter_Db2 class.
*
* @license New BSD License
* @param string $table
* @return string
*/
public function getListTableColumnsSQL($table)
{
return "SELECT DISTINCT c.tabschema, c.tabname, c.colname, c.colno,
c.typename, c.default, c.nulls, c.length, c.scale,
c.identity, tc.type AS tabconsttype, k.colseq
FROM syscat.columns c
LEFT JOIN (syscat.keycoluse k JOIN syscat.tabconst tc
ON (k.tabschema = tc.tabschema
AND k.tabname = tc.tabname
AND tc.type = 'P'))
ON (c.tabschema = k.tabschema
AND c.tabname = k.tabname
AND c.colname = k.colname)
WHERE UPPER(c.tabname) = UPPER('" . $table . "') ORDER BY c.colno";
}
public function getListTablesSQL()
{
return "SELECT NAME FROM SYSIBM.SYSTABLES WHERE TYPE = 'T'";
}
public function getListUsersSQL()
{
throw DBALException::notSupported(__METHOD__);
}
/**
* Get the SQL to list all views of a database or user.
*
* @param string $database
* @return string
*/
public function getListViewsSQL($database)
{
return "SELECT NAME, TEXT FROM SYSIBM.SYSVIEWS";
}
public function getListTableIndexesSQL($table)
{
return "SELECT NAME, COLNAMES, UNIQUERULE FROM SYSIBM.SYSINDEXES WHERE TBNAME = UPPER('" . $table . "')";
}
public function getListTableForeignKeysSQL($table)
{
return "SELECT TBNAME, RELNAME, REFTBNAME, DELETERULE, UPDATERULE, FKCOLNAMES, PKCOLNAMES ".
"FROM SYSIBM.SYSRELS WHERE TBNAME = UPPER('".$table."')";
}
public function getCreateViewSQL($name, $sql)
{
return "CREATE VIEW ".$name." AS ".$sql;
}
public function getDropViewSQL($name)
{
return "DROP VIEW ".$name;
}
public function getDropSequenceSQL($sequence)
{
throw DBALException::notSupported(__METHOD__);
}
public function getSequenceNextValSQL($sequenceName)
{
throw DBALException::notSupported(__METHOD__);
}
public function getCreateDatabaseSQL($database)
{
return "CREATE DATABASE ".$database;
}
public function getDropDatabaseSQL($database)
{
return "DROP DATABASE ".$database.";";
}
public function supportsCreateDropDatabase()
{
return false;
}
/**
* Whether the platform supports releasing savepoints.
*
* @return boolean
*/
public function supportsReleaseSavepoints()
{
return false;
}
/**
* Gets the SQL specific for the platform to get the current date.
*
* @return string
*/
public function getCurrentDateSQL()
{
return 'VALUES CURRENT DATE';
}
/**
* Gets the SQL specific for the platform to get the current time.
*
* @return string
*/
public function getCurrentTimeSQL()
{
return 'VALUES CURRENT TIME';
}
/**
* Gets the SQL specific for the platform to get the current timestamp
*
* @return string
*/
public function getCurrentTimestampSQL()
{
return "VALUES CURRENT TIMESTAMP";
}
/**
* Obtain DBMS specific SQL code portion needed to set an index
* declaration to be used in statements like CREATE TABLE.
*
* @param string $name name of the index
* @param Index $index index definition
* @return string DBMS specific SQL code portion needed to set an index
*/
public function getIndexDeclarationSQL($name, Index $index)
{
return $this->getUniqueConstraintDeclarationSQL($name, $index);
}
/**
* @param string $tableName
* @param array $columns
* @param array $options
* @return array
*/
protected function _getCreateTableSQL($tableName, array $columns, array $options = array())
{
$indexes = array();
if (isset($options['indexes'])) {
$indexes = $options['indexes'];
}
$options['indexes'] = array();
$sqls = parent::_getCreateTableSQL($tableName, $columns, $options);
foreach ($indexes as $index => $definition) {
$sqls[] = $this->getCreateIndexSQL($definition, $tableName);
}
return $sqls;
}
/**
* Gets the SQL to alter an existing table.
*
* @param TableDiff $diff
* @return array
*/
public function getAlterTableSQL(TableDiff $diff)
{
$sql = array();
$queryParts = array();
foreach ($diff->addedColumns AS $fieldName => $column) {
$queryParts[] = 'ADD COLUMN ' . $this->getColumnDeclarationSQL($column->getName(), $column->toArray());
}
foreach ($diff->removedColumns AS $column) {
$queryParts[] = 'DROP COLUMN ' . $column->getName();
}
foreach ($diff->changedColumns AS $columnDiff) {
/* @var $columnDiff Doctrine\DBAL\Schema\ColumnDiff */
$column = $columnDiff->column;
$queryParts[] = 'ALTER ' . ($columnDiff->oldColumnName) . ' '
. $this->getColumnDeclarationSQL($column->getName(), $column->toArray());
}
foreach ($diff->renamedColumns AS $oldColumnName => $column) {
$queryParts[] = 'RENAME ' . $oldColumnName . ' TO ' . $column->getName();
}
if (count($queryParts) > 0) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' ' . implode(" ", $queryParts);
}
$sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff));
if ($diff->newName !== false) {
$sql[] = 'RENAME TABLE TO ' . $diff->newName;
}
return $sql;
}
public function getDefaultValueDeclarationSQL($field)
{
if (isset($field['notnull']) && $field['notnull'] && !isset($field['default'])) {
if (in_array((string)$field['type'], array("Integer", "BigInteger", "SmallInteger"))) {
$field['default'] = 0;
} else if((string)$field['type'] == "DateTime") {
$field['default'] = "00-00-00 00:00:00";
} else if ((string)$field['type'] == "Date") {
$field['default'] = "00-00-00";
} else if((string)$field['type'] == "Time") {
$field['default'] = "00:00:00";
} else {
$field['default'] = '';
}
}
unset($field['default']); // @todo this needs fixing
if (isset($field['version']) && $field['version']) {
if ((string)$field['type'] != "DateTime") {
$field['default'] = "1";
}
}
return parent::getDefaultValueDeclarationSQL($field);
}
/**
* Get the insert sql for an empty insert statement
*
* @param string $tableName
* @param string $identifierColumnName
* @return string $sql
*/
public function getEmptyIdentityInsertSQL($tableName, $identifierColumnName)
{
return 'INSERT INTO ' . $tableName . ' (' . $identifierColumnName . ') VALUES (DEFAULT)';
}
public function getCreateTemporaryTableSnippetSQL()
{
return "DECLARE GLOBAL TEMPORARY TABLE";
}
/**
* DB2 automatically moves temporary tables into the SESSION. schema.
*
* @param string $tableName
* @return string
*/
public function getTemporaryTableName($tableName)
{
return "SESSION." . $tableName;
}
public function modifyLimitQuery($query, $limit, $offset = null)
{
if ($limit === null && $offset === null) {
return $query;
}
$limit = (int)$limit;
$offset = (int)(($offset)?:0);
// Todo OVER() needs ORDER BY data!
$sql = 'SELECT db22.* FROM (SELECT ROW_NUMBER() OVER() AS DC_ROWNUM, db21.* '.
'FROM (' . $query . ') db21) db22 WHERE db22.DC_ROWNUM BETWEEN ' . ($offset+1) .' AND ' . ($offset+$limit);
return $sql;
}
/**
* returns the position of the first occurrence of substring $substr in string $str
*
* @param string $substr literal string to find
* @param string $str literal string
* @param int $pos position to start at, beginning of string by default
* @return integer
*/
public function getLocateExpression($str, $substr, $startPos = false)
{
if ($startPos == false) {
return 'LOCATE(' . $substr . ', ' . $str . ')';
} else {
return 'LOCATE(' . $substr . ', ' . $str . ', '.$startPos.')';
}
}
/**
* return string to call a function to get a substring inside an SQL statement
*
* Note: Not SQL92, but common functionality.
*
* SQLite only supports the 2 parameter variant of this function
*
* @param string $value an sql string literal or column name/alias
* @param integer $from where to start the substring portion
* @param integer $len the substring portion length
* @return string
*/
public function getSubstringExpression($value, $from, $len = null)
{
if ($len === null)
return 'SUBSTR(' . $value . ', ' . $from . ')';
else {
return 'SUBSTR(' . $value . ', ' . $from . ', ' . $len . ')';
}
}
public function supportsIdentityColumns()
{
return true;
}
public function prefersIdentityColumns()
{
return true;
}
/**
* Gets the character casing of a column in an SQL result set of this platform.
*
* DB2 returns all column names in SQL result sets in uppercase.
*
* @param string $column The column name for which to get the correct character casing.
* @return string The column name in the character casing used in SQL result sets.
*/
public function getSQLResultCasing($column)
{
return strtoupper($column);
}
public function getForUpdateSQL()
{
return ' WITH RR USE AND KEEP UPDATE LOCKS';
}
public function getDummySelectSQL()
{
return 'SELECT 1 FROM sysibm.sysdummy1';
}
/**
* DB2 supports savepoints, but they work semantically different than on other vendor platforms.
*
* TODO: We have to investigate how to get DB2 up and running with savepoints.
*
* @return bool
*/
public function supportsSavepoints()
{
return false;
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms;
use Doctrine\DBAL\DBALException,
Doctrine\DBAL\Schema\TableDiff;
/**
* The MySqlPlatform provides the behavior, features and SQL dialect of the
* MySQL database platform. This platform represents a MySQL 5.0 or greater platform that
* uses the InnoDB storage engine.
*
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @todo Rename: MySQLPlatform
*/
class MySqlPlatform extends AbstractPlatform
{
/**
* Gets the character used for identifier quoting.
*
* @return string
* @override
*/
public function getIdentifierQuoteCharacter()
{
return '`';
}
/**
* Returns the regular expression operator.
*
* @return string
* @override
*/
public function getRegexpExpression()
{
return 'RLIKE';
}
/**
* Returns global unique identifier
*
* @return string to get global unique identifier
* @override
*/
public function getGuidExpression()
{
return 'UUID()';
}
/**
* returns the position of the first occurrence of substring $substr in string $str
*
* @param string $substr literal string to find
* @param string $str literal string
* @param int $pos position to start at, beginning of string by default
* @return integer
*/
public function getLocateExpression($str, $substr, $startPos = false)
{
if ($startPos == false) {
return 'LOCATE(' . $substr . ', ' . $str . ')';
} else {
return 'LOCATE(' . $substr . ', ' . $str . ', '.$startPos.')';
}
}
/**
* Returns a series of strings concatinated
*
* concat() accepts an arbitrary number of parameters. Each parameter
* must contain an expression or an array with expressions.
*
* @param string|array(string) strings that will be concatinated.
* @override
*/
public function getConcatExpression()
{
$args = func_get_args();
return 'CONCAT(' . join(', ', (array) $args) . ')';
}
public function getListDatabasesSQL()
{
return 'SHOW DATABASES';
}
public function getListTableConstraintsSQL($table)
{
return 'SHOW INDEX FROM ' . $table;
}
public function getListTableIndexesSQL($table)
{
return 'SHOW INDEX FROM ' . $table;
}
public function getListViewsSQL($database)
{
return "SELECT * FROM information_schema.VIEWS WHERE TABLE_SCHEMA = '".$database."'";
}
public function getListTableForeignKeysSQL($table, $database = null)
{
$sql = "SELECT DISTINCT k.`CONSTRAINT_NAME`, k.`COLUMN_NAME`, k.`REFERENCED_TABLE_NAME`, ".
"k.`REFERENCED_COLUMN_NAME` /*!50116 , c.update_rule, c.delete_rule */ ".
"FROM information_schema.key_column_usage k /*!50116 ".
"INNER JOIN information_schema.referential_constraints c ON ".
" c.constraint_name = k.constraint_name AND ".
" c.table_name = '$table' */ WHERE k.table_name = '$table'";
if ($database) {
$sql .= " AND k.table_schema = '$database' /*!50116 AND c.constraint_schema = '$database' */";
}
$sql .= " AND k.`REFERENCED_COLUMN_NAME` is not NULL";
return $sql;
}
public function getCreateViewSQL($name, $sql)
{
return 'CREATE VIEW ' . $name . ' AS ' . $sql;
}
public function getDropViewSQL($name)
{
return 'DROP VIEW '. $name;
}
/**
* Gets the SQL snippet used to declare a VARCHAR column on the MySql platform.
*
* @params array $field
*/
public function getVarcharTypeDeclarationSQL(array $field)
{
if ( ! isset($field['length'])) {
if (array_key_exists('default', $field)) {
$field['length'] = $this->getVarcharMaxLength();
} else {
$field['length'] = false;
}
}
$length = ($field['length'] <= $this->getVarcharMaxLength()) ? $field['length'] : false;
$fixed = (isset($field['fixed'])) ? $field['fixed'] : false;
return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)')
: ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)');
}
/** @override */
public function getClobTypeDeclarationSQL(array $field)
{
if ( ! empty($field['length']) && is_numeric($field['length'])) {
$length = $field['length'];
if ($length <= 255) {
return 'TINYTEXT';
} else if ($length <= 65532) {
return 'TEXT';
} else if ($length <= 16777215) {
return 'MEDIUMTEXT';
}
}
return 'LONGTEXT';
}
/**
* @override
*/
public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
{
if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] == true) {
return 'TIMESTAMP';
} else {
return 'DATETIME';
}
}
/**
* @override
*/
public function getDateTypeDeclarationSQL(array $fieldDeclaration)
{
return 'DATE';
}
/**
* @override
*/
public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
{
return 'TIME';
}
/**
* @override
*/
public function getBooleanTypeDeclarationSQL(array $field)
{
return 'TINYINT(1)';
}
/**
* Obtain DBMS specific SQL code portion needed to set the COLLATION
* of a field declaration to be used in statements like CREATE TABLE.
*
* @param string $collation name of the collation
* @return string DBMS specific SQL code portion needed to set the COLLATION
* of a field declaration.
*/
public function getCollationFieldDeclaration($collation)
{
return 'COLLATE ' . $collation;
}
/**
* Whether the platform prefers identity columns for ID generation.
* MySql prefers "autoincrement" identity columns since sequences can only
* be emulated with a table.
*
* @return boolean
* @override
*/
public function prefersIdentityColumns()
{
return true;
}
/**
* Whether the platform supports identity columns.
* MySql supports this through AUTO_INCREMENT columns.
*
* @return boolean
* @override
*/
public function supportsIdentityColumns()
{
return true;
}
public function getShowDatabasesSQL()
{
return 'SHOW DATABASES';
}
public function getListTablesSQL()
{
return 'SHOW FULL TABLES WHERE Table_type = "BASE TABLE"';
}
public function getListTableColumnsSQL($table)
{
return 'DESCRIBE ' . $table;
}
/**
* create a new database
*
* @param string $name name of the database that should be created
* @return string
* @override
*/
public function getCreateDatabaseSQL($name)
{
return 'CREATE DATABASE ' . $name;
}
/**
* drop an existing database
*
* @param string $name name of the database that should be dropped
* @return string
* @override
*/
public function getDropDatabaseSQL($name)
{
return 'DROP DATABASE ' . $name;
}
/**
* create a new table
*
* @param string $tableName Name of the database that should be created
* @param array $columns Associative array that contains the definition of each field of the new table
* The indexes of the array entries are the names of the fields of the table an
* the array entry values are associative arrays like those that are meant to be
* passed with the field definitions to get[Type]Declaration() functions.
* array(
* 'id' => array(
* 'type' => 'integer',
* 'unsigned' => 1
* 'notnull' => 1
* 'default' => 0
* ),
* 'name' => array(
* 'type' => 'text',
* 'length' => 12
* ),
* 'password' => array(
* 'type' => 'text',
* 'length' => 12
* )
* );
* @param array $options An associative array of table options:
* array(
* 'comment' => 'Foo',
* 'charset' => 'utf8',
* 'collate' => 'utf8_unicode_ci',
* 'type' => 'innodb',
* );
*
* @return void
* @override
*/
protected function _getCreateTableSQL($tableName, array $columns, array $options = array())
{
$queryFields = $this->getColumnDeclarationListSQL($columns);
if (isset($options['uniqueConstraints']) && ! empty($options['uniqueConstraints'])) {
foreach ($options['uniqueConstraints'] as $index => $definition) {
$queryFields .= ', ' . $this->getUniqueConstraintDeclarationSQL($index, $definition);
}
}
// add all indexes
if (isset($options['indexes']) && ! empty($options['indexes'])) {
foreach($options['indexes'] as $index => $definition) {
$queryFields .= ', ' . $this->getIndexDeclarationSQL($index, $definition);
}
}
// attach all primary keys
if (isset($options['primary']) && ! empty($options['primary'])) {
$keyColumns = array_unique(array_values($options['primary']));
$queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')';
}
$query = 'CREATE ';
if (!empty($options['temporary'])) {
$query .= 'TEMPORARY ';
}
$query.= 'TABLE ' . $tableName . ' (' . $queryFields . ')';
$optionStrings = array();
if (isset($options['comment'])) {
$optionStrings['comment'] = 'COMMENT = ' . $this->quote($options['comment'], 'text');
}
if (isset($options['charset'])) {
$optionStrings['charset'] = 'DEFAULT CHARACTER SET ' . $options['charset'];
if (isset($options['collate'])) {
$optionStrings['charset'] .= ' COLLATE ' . $options['collate'];
}
}
// get the type of the table
if (isset($options['engine'])) {
$optionStrings[] = 'ENGINE = ' . $options['engine'];
} else {
// default to innodb
$optionStrings[] = 'ENGINE = InnoDB';
}
if ( ! empty($optionStrings)) {
$query.= ' '.implode(' ', $optionStrings);
}
$sql[] = $query;
if (isset($options['foreignKeys'])) {
foreach ((array) $options['foreignKeys'] as $definition) {
$sql[] = $this->getCreateForeignKeySQL($definition, $tableName);
}
}
return $sql;
}
/**
* Gets the SQL to alter an existing table.
*
* @param TableDiff $diff
* @return array
*/
public function getAlterTableSQL(TableDiff $diff)
{
$queryParts = array();
if ($diff->newName !== false) {
$queryParts[] = 'RENAME TO ' . $diff->newName;
}
foreach ($diff->addedColumns AS $fieldName => $column) {
$queryParts[] = 'ADD ' . $this->getColumnDeclarationSQL($column->getName(), $column->toArray());
}
foreach ($diff->removedColumns AS $column) {
$queryParts[] = 'DROP ' . $column->getName();
}
foreach ($diff->changedColumns AS $columnDiff) {
/* @var $columnDiff Doctrine\DBAL\Schema\ColumnDiff */
$column = $columnDiff->column;
$queryParts[] = 'CHANGE ' . ($columnDiff->oldColumnName) . ' '
. $this->getColumnDeclarationSQL($column->getName(), $column->toArray());
}
foreach ($diff->renamedColumns AS $oldColumnName => $column) {
$queryParts[] = 'CHANGE ' . $oldColumnName . ' '
. $this->getColumnDeclarationSQL($column->getName(), $column->toArray());
}
$sql = array();
if (count($queryParts) > 0) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' ' . implode(", ", $queryParts);
}
$sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff));
return $sql;
}
/**
* Obtain DBMS specific SQL code portion needed to declare an integer type
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param string $field associative array with the name of the properties
* of the field being declared as array indexes.
* Currently, the types of supported field
* properties are as follows:
*
* unsigned
* Boolean flag that indicates whether the field
* should be declared as unsigned integer if
* possible.
*
* default
* Integer value to be used as default for this
* field.
*
* notnull
* Boolean flag that indicates whether this field is
* constrained to not be set to null.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @override
*/
public function getIntegerTypeDeclarationSQL(array $field)
{
return 'INT' . $this->_getCommonIntegerTypeDeclarationSQL($field);
}
/** @override */
public function getBigIntTypeDeclarationSQL(array $field)
{
return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($field);
}
/** @override */
public function getSmallIntTypeDeclarationSQL(array $field)
{
return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($field);
}
/** @override */
protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef)
{
$autoinc = '';
if ( ! empty($columnDef['autoincrement'])) {
$autoinc = ' AUTO_INCREMENT';
}
$unsigned = (isset($columnDef['unsigned']) && $columnDef['unsigned']) ? ' UNSIGNED' : '';
return $unsigned . $autoinc;
}
/**
* Return the FOREIGN KEY query section dealing with non-standard options
* as MATCH, INITIALLY DEFERRED, ON UPDATE, ...
*
* @param ForeignKeyConstraint $foreignKey
* @return string
* @override
*/
public function getAdvancedForeignKeyOptionsSQL(\Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey)
{
$query = '';
if ($foreignKey->hasOption('match')) {
$query .= ' MATCH ' . $foreignKey->getOption('match');
}
$query .= parent::getAdvancedForeignKeyOptionsSQL($foreignKey);
return $query;
}
/**
* Gets the SQL to drop an index of a table.
*
* @param Index $index name of the index to be dropped
* @param string|Table $table name of table that should be used in method
* @override
*/
public function getDropIndexSQL($index, $table=null)
{
if($index instanceof \Doctrine\DBAL\Schema\Index) {
$index = $index->getName();
} else if(!is_string($index)) {
throw new \InvalidArgumentException('MysqlPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.');
}
if($table instanceof \Doctrine\DBAL\Schema\Table) {
$table = $table->getName();
} else if(!is_string($table)) {
throw new \InvalidArgumentException('MysqlPlatform::getDropIndexSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.');
}
return 'DROP INDEX ' . $index . ' ON ' . $table;
}
/**
* Gets the SQL to drop a table.
*
* @param string $table The name of table to drop.
* @override
*/
public function getDropTableSQL($table)
{
if ($table instanceof \Doctrine\DBAL\Schema\Table) {
$table = $table->getName();
} else if(!is_string($table)) {
throw new \InvalidArgumentException('MysqlPlatform::getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.');
}
return 'DROP TABLE ' . $table;
}
public function getSetTransactionIsolationSQL($level)
{
return 'SET SESSION TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level);
}
/**
* Get the platform name for this instance.
*
* @return string
*/
public function getName()
{
return 'mysql';
}
public function getReadLockSQL()
{
return 'LOCK IN SHARE MODE';
}
protected function initializeDoctrineTypeMappings()
{
$this->doctrineTypeMapping = array(
'tinyint' => 'boolean',
'smallint' => 'smallint',
'mediumint' => 'integer',
'int' => 'integer',
'integer' => 'integer',
'bigint' => 'bigint',
'tinytext' => 'text',
'mediumtext' => 'text',
'longtext' => 'text',
'text' => 'text',
'varchar' => 'string',
'string' => 'string',
'char' => 'string',
'date' => 'date',
'datetime' => 'datetime',
'timestamp' => 'datetime',
'time' => 'time',
'float' => 'decimal',
'double' => 'decimal',
'real' => 'decimal',
'decimal' => 'decimal',
'numeric' => 'decimal',
'year' => 'date',
);
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms;
use Doctrine\DBAL\DBALException,
Doctrine\DBAL\Connection,
Doctrine\DBAL\Types,
Doctrine\DBAL\Schema\Table,
Doctrine\DBAL\Schema\Index,
Doctrine\DBAL\Schema\ForeignKeyConstraint,
Doctrine\DBAL\Schema\TableDiff;
/**
* Base class for all DatabasePlatforms. The DatabasePlatforms are the central
* point of abstraction of platform-specific behaviors, features and SQL dialects.
* They are a passive source of information.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @todo Remove any unnecessary methods.
*/
abstract class AbstractPlatform
{
/**
* @var int
*/
const CREATE_INDEXES = 1;
/**
* @var int
*/
const CREATE_FOREIGNKEYS = 2;
/**
* @var int
*/
const TRIM_UNSPECIFIED = 0;
/**
* @var int
*/
const TRIM_LEADING = 1;
/**
* @var int
*/
const TRIM_TRAILING = 2;
/**
* @var int
*/
const TRIM_BOTH = 3;
/**
* @var array
*/
protected $doctrineTypeMapping = null;
/**
* Constructor.
*/
public function __construct() {}
/**
* Gets the SQL snippet that declares a boolean column.
*
* @param array $columnDef
* @return string
*/
abstract public function getBooleanTypeDeclarationSQL(array $columnDef);
/**
* Gets the SQL snippet that declares a 4 byte integer column.
*
* @param array $columnDef
* @return string
*/
abstract public function getIntegerTypeDeclarationSQL(array $columnDef);
/**
* Gets the SQL snippet that declares an 8 byte integer column.
*
* @param array $columnDef
* @return string
*/
abstract public function getBigIntTypeDeclarationSQL(array $columnDef);
/**
* Gets the SQL snippet that declares a 2 byte integer column.
*
* @param array $columnDef
* @return string
*/
abstract public function getSmallIntTypeDeclarationSQL(array $columnDef);
/**
* Gets the SQL snippet that declares common properties of an integer column.
*
* @param array $columnDef
* @return string
*/
abstract protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef);
/**
* Lazy load Doctrine Type Mappings
*
* @return void
*/
abstract protected function initializeDoctrineTypeMappings();
/**
* Gets the SQL snippet used to declare a VARCHAR column type.
*
* @param array $field
*/
abstract public function getVarcharTypeDeclarationSQL(array $field);
/**
* Gets the SQL snippet used to declare a CLOB column type.
*
* @param array $field
*/
abstract public function getClobTypeDeclarationSQL(array $field);
/**
* Gets the name of the platform.
*
* @return string
*/
abstract public function getName();
/**
* Register a doctrine type to be used in conjunction with a column type of this platform.
*
* @param string $dbType
* @param string $doctrineType
*/
public function registerDoctrineTypeMapping($dbType, $doctrineType)
{
if ($this->doctrineTypeMapping === null) {
$this->initializeDoctrineTypeMappings();
}
if (!Types\Type::hasType($doctrineType)) {
throw DBALException::typeNotFound($doctrineType);
}
$dbType = strtolower($dbType);
$this->doctrineTypeMapping[$dbType] = $doctrineType;
}
/**
* Get the Doctrine type that is mapped for the given database column type.
*
* @param string $dbType
* @return string
*/
public function getDoctrineTypeMapping($dbType)
{
if ($this->doctrineTypeMapping === null) {
$this->initializeDoctrineTypeMappings();
}
$dbType = strtolower($dbType);
if (isset($this->doctrineTypeMapping[$dbType])) {
return $this->doctrineTypeMapping[$dbType];
} else {
throw new \Doctrine\DBAL\DBALException("Unknown database type ".$dbType." requested, " . get_class($this) . " may not support it.");
}
}
/**
* Check if a database type is currently supported by this platform.
*
* @param string $dbType
* @return bool
*/
public function hasDoctrineTypeMappingFor($dbType)
{
if ($this->doctrineTypeMapping === null) {
$this->initializeDoctrineTypeMappings();
}
$dbType = strtolower($dbType);
return isset($this->doctrineTypeMapping[$dbType]);
}
/**
* Gets the character used for identifier quoting.
*
* @return string
*/
public function getIdentifierQuoteCharacter()
{
return '"';
}
/**
* Gets the string portion that starts an SQL comment.
*
* @return string
*/
public function getSqlCommentStartString()
{
return "--";
}
/**
* Gets the string portion that ends an SQL comment.
*
* @return string
*/
public function getSqlCommentEndString()
{
return "\n";
}
/**
* Gets the maximum length of a varchar field.
*
* @return integer
*/
public function getVarcharMaxLength()
{
return 255;
}
/**
* Gets all SQL wildcard characters of the platform.
*
* @return array
*/
public function getWildcards()
{
return array('%', '_');
}
/**
* Returns the regular expression operator.
*
* @return string
*/
public function getRegexpExpression()
{
throw DBALException::notSupported(__METHOD__);
}
/**
* Returns the average value of a column
*
* @param string $column the column to use
* @return string generated sql including an AVG aggregate function
*/
public function getAvgExpression($column)
{
return 'AVG(' . $column . ')';
}
/**
* Returns the number of rows (without a NULL value) of a column
*
* If a '*' is used instead of a column the number of selected rows
* is returned.
*
* @param string|integer $column the column to use
* @return string generated sql including a COUNT aggregate function
*/
public function getCountExpression($column)
{
return 'COUNT(' . $column . ')';
}
/**
* Returns the highest value of a column
*
* @param string $column the column to use
* @return string generated sql including a MAX aggregate function
*/
public function getMaxExpression($column)
{
return 'MAX(' . $column . ')';
}
/**
* Returns the lowest value of a column
*
* @param string $column the column to use
* @return string
*/
public function getMinExpression($column)
{
return 'MIN(' . $column . ')';
}
/**
* Returns the total sum of a column
*
* @param string $column the column to use
* @return string
*/
public function getSumExpression($column)
{
return 'SUM(' . $column . ')';
}
// scalar functions
/**
* Returns the md5 sum of a field.
*
* Note: Not SQL92, but common functionality
*
* @return string
*/
public function getMd5Expression($column)
{
return 'MD5(' . $column . ')';
}
/**
* Returns the length of a text field.
*
* @param string $expression1
* @param string $expression2
* @return string
*/
public function getLengthExpression($column)
{
return 'LENGTH(' . $column . ')';
}
/**
* Rounds a numeric field to the number of decimals specified.
*
* @param string $expression1
* @param string $expression2
* @return string
*/
public function getRoundExpression($column, $decimals = 0)
{
return 'ROUND(' . $column . ', ' . $decimals . ')';
}
/**
* Returns the remainder of the division operation
* $expression1 / $expression2.
*
* @param string $expression1
* @param string $expression2
* @return string
*/
public function getModExpression($expression1, $expression2)
{
return 'MOD(' . $expression1 . ', ' . $expression2 . ')';
}
/**
* Trim a string, leading/trailing/both and with a given char which defaults to space.
*
* @param string $str
* @param int $pos
* @param string $char has to be quoted already
* @return string
*/
public function getTrimExpression($str, $pos = self::TRIM_UNSPECIFIED, $char = false)
{
$posStr = '';
$trimChar = ($char != false) ? $char . ' FROM ' : '';
if ($pos == self::TRIM_LEADING) {
$posStr = 'LEADING '.$trimChar;
} else if($pos == self::TRIM_TRAILING) {
$posStr = 'TRAILING '.$trimChar;
} else if($pos == self::TRIM_BOTH) {
$posStr = 'BOTH '.$trimChar;
}
return 'TRIM(' . $posStr . $str . ')';
}
/**
* rtrim
* returns the string $str with proceeding space characters removed
*
* @param string $str literal string or column name
* @return string
*/
public function getRtrimExpression($str)
{
return 'RTRIM(' . $str . ')';
}
/**
* ltrim
* returns the string $str with leading space characters removed
*
* @param string $str literal string or column name
* @return string
*/
public function getLtrimExpression($str)
{
return 'LTRIM(' . $str . ')';
}
/**
* upper
* Returns the string $str with all characters changed to
* uppercase according to the current character set mapping.
*
* @param string $str literal string or column name
* @return string
*/
public function getUpperExpression($str)
{
return 'UPPER(' . $str . ')';
}
/**
* lower
* Returns the string $str with all characters changed to
* lowercase according to the current character set mapping.
*
* @param string $str literal string or column name
* @return string
*/
public function getLowerExpression($str)
{
return 'LOWER(' . $str . ')';
}
/**
* returns the position of the first occurrence of substring $substr in string $str
*
* @param string $substr literal string to find
* @param string $str literal string
* @param int $pos position to start at, beginning of string by default
* @return integer
*/
public function getLocateExpression($str, $substr, $startPos = false)
{
throw DBALException::notSupported(__METHOD__);
}
/**
* Returns the current system date.
*
* @return string
*/
public function getNowExpression()
{
return 'NOW()';
}
/**
* return string to call a function to get a substring inside an SQL statement
*
* Note: Not SQL92, but common functionality.
*
* SQLite only supports the 2 parameter variant of this function
*
* @param string $value an sql string literal or column name/alias
* @param integer $from where to start the substring portion
* @param integer $len the substring portion length
* @return string
*/
public function getSubstringExpression($value, $from, $len = null)
{
if ($len === null)
return 'SUBSTRING(' . $value . ' FROM ' . $from . ')';
else {
return 'SUBSTRING(' . $value . ' FROM ' . $from . ' FOR ' . $len . ')';
}
}
/**
* Returns a series of strings concatinated
*
* concat() accepts an arbitrary number of parameters. Each parameter
* must contain an expression
*
* @param string $arg1, $arg2 ... $argN strings that will be concatinated.
* @return string
*/
public function getConcatExpression()
{
return join(' || ' , func_get_args());
}
/**
* Returns the SQL for a logical not.
*
* Example:
* <code>
* $q = new Doctrine_Query();
* $e = $q->expr;
* $q->select('*')->from('table')
* ->where($e->eq('id', $e->not('null'));
* </code>
*
* @return string a logical expression
*/
public function getNotExpression($expression)
{
return 'NOT(' . $expression . ')';
}
/**
* Returns the SQL to check if a value is one in a set of
* given values.
*
* in() accepts an arbitrary number of parameters. The first parameter
* must always specify the value that should be matched against. Successive
* must contain a logical expression or an array with logical expressions.
* These expressions will be matched against the first parameter.
*
* @param string $column the value that should be matched against
* @param string|array(string) values that will be matched against $column
* @return string logical expression
*/
public function getInExpression($column, $values)
{
if ( ! is_array($values)) {
$values = array($values);
}
$values = $this->getIdentifiers($values);
if (count($values) == 0) {
throw \InvalidArgumentException('Values must not be empty.');
}
return $column . ' IN (' . implode(', ', $values) . ')';
}
/**
* Returns SQL that checks if a expression is null.
*
* @param string $expression the expression that should be compared to null
* @return string logical expression
*/
public function getIsNullExpression($expression)
{
return $expression . ' IS NULL';
}
/**
* Returns SQL that checks if a expression is not null.
*
* @param string $expression the expression that should be compared to null
* @return string logical expression
*/
public function getIsNotNullExpression($expression)
{
return $expression . ' IS NOT NULL';
}
/**
* Returns SQL that checks if an expression evaluates to a value between
* two values.
*
* The parameter $expression is checked if it is between $value1 and $value2.
*
* Note: There is a slight difference in the way BETWEEN works on some databases.
* http://www.w3schools.com/sql/sql_between.asp. If you want complete database
* independence you should avoid using between().
*
* @param string $expression the value to compare to
* @param string $value1 the lower value to compare with
* @param string $value2 the higher value to compare with
* @return string logical expression
*/
public function getBetweenExpression($expression, $value1, $value2)
{
return $expression . ' BETWEEN ' .$value1 . ' AND ' . $value2;
}
public function getAcosExpression($value)
{
return 'ACOS(' . $value . ')';
}
public function getSinExpression($value)
{
return 'SIN(' . $value . ')';
}
public function getPiExpression()
{
return 'PI()';
}
public function getCosExpression($value)
{
return 'COS(' . $value . ')';
}
public function getForUpdateSQL()
{
return 'FOR UPDATE';
}
/**
* Honors that some SQL vendors such as MsSql use table hints for locking instead of the ANSI SQL FOR UPDATE specification.
*
* @param string $fromClause
* @param int $lockMode
* @return string
*/
public function appendLockHint($fromClause, $lockMode)
{
return $fromClause;
}
/**
* Get the sql snippet to append to any SELECT statement which locks rows in shared read lock.
*
* This defaults to the ASNI SQL "FOR UPDATE", which is an exclusive lock (Write). Some database
* vendors allow to lighten this constraint up to be a real read lock.
*
* @return string
*/
public function getReadLockSQL()
{
return $this->getForUpdateSQL();
}
/**
* Get the SQL snippet to append to any SELECT statement which obtains an exclusive lock on the rows.
*
* The semantics of this lock mode should equal the SELECT .. FOR UPDATE of the ASNI SQL standard.
*
* @return string
*/
public function getWriteLockSQL()
{
return $this->getForUpdateSQL();
}
public function getDropDatabaseSQL($database)
{
return 'DROP DATABASE ' . $database;
}
/**
* Drop a Table
*
* @param Table|string $table
* @return string
*/
public function getDropTableSQL($table)
{
if ($table instanceof \Doctrine\DBAL\Schema\Table) {
$table = $table->getName();
}
return 'DROP TABLE ' . $table;
}
/**
* Drop index from a table
*
* @param Index|string $name
* @param string|Table $table
* @return string
*/
public function getDropIndexSQL($index, $table=null)
{
if($index instanceof \Doctrine\DBAL\Schema\Index) {
$index = $index->getName();
} else if(!is_string($index)) {
throw new \InvalidArgumentException('AbstractPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.');
}
return 'DROP INDEX ' . $index;
}
/**
* Get drop constraint sql
*
* @param \Doctrine\DBAL\Schema\Constraint $constraint
* @param string|Table $table
* @return string
*/
public function getDropConstraintSQL($constraint, $table)
{
if ($constraint instanceof \Doctrine\DBAL\Schema\Constraint) {
$constraint = $constraint->getName();
}
if ($table instanceof \Doctrine\DBAL\Schema\Table) {
$table = $table->getName();
}
return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $constraint;
}
/**
* @param ForeignKeyConstraint|string $foreignKey
* @param Table|string $table
* @return string
*/
public function getDropForeignKeySQL($foreignKey, $table)
{
if ($foreignKey instanceof \Doctrine\DBAL\Schema\ForeignKeyConstraint) {
$foreignKey = $foreignKey->getName();
}
if ($table instanceof \Doctrine\DBAL\Schema\Table) {
$table = $table->getName();
}
return 'ALTER TABLE ' . $table . ' DROP FOREIGN KEY ' . $foreignKey;
}
/**
* Gets the SQL statement(s) to create a table with the specified name, columns and constraints
* on this platform.
*
* @param string $table The name of the table.
* @param int $createFlags
* @return array The sequence of SQL statements.
*/
public function getCreateTableSQL(Table $table, $createFlags=self::CREATE_INDEXES)
{
if ( ! is_int($createFlags)) {
throw new \InvalidArgumentException("Second argument of AbstractPlatform::getCreateTableSQL() has to be integer.");
}
if (count($table->getColumns()) == 0) {
throw DBALException::noColumnsSpecifiedForTable($table->getName());
}
$tableName = $table->getName();
$options = $table->getOptions();
$options['uniqueConstraints'] = array();
$options['indexes'] = array();
$options['primary'] = array();
if (($createFlags&self::CREATE_INDEXES) > 0) {
foreach ($table->getIndexes() AS $index) {
/* @var $index Index */
if ($index->isPrimary()) {
$options['primary'] = $index->getColumns();
} else {
$options['indexes'][$index->getName()] = $index;
}
}
}
$columns = array();
foreach ($table->getColumns() AS $column) {
/* @var \Doctrine\DBAL\Schema\Column $column */
$columnData = array();
$columnData['name'] = $column->getName();
$columnData['type'] = $column->getType();
$columnData['length'] = $column->getLength();
$columnData['notnull'] = $column->getNotNull();
$columnData['unique'] = false; // TODO: what do we do about this?
$columnData['version'] = ($column->hasPlatformOption("version"))?$column->getPlatformOption('version'):false;
if(strtolower($columnData['type']) == "string" && $columnData['length'] === null) {
$columnData['length'] = 255;
}
$columnData['precision'] = $column->getPrecision();
$columnData['scale'] = $column->getScale();
$columnData['default'] = $column->getDefault();
$columnData['columnDefinition'] = $column->getColumnDefinition();
$columnData['autoincrement'] = $column->getAutoincrement();
if(in_array($column->getName(), $options['primary'])) {
$columnData['primary'] = true;
}
$columns[$columnData['name']] = $columnData;
}
if (($createFlags&self::CREATE_FOREIGNKEYS) > 0) {
$options['foreignKeys'] = array();
foreach ($table->getForeignKeys() AS $fkConstraint) {
$options['foreignKeys'][] = $fkConstraint;
}
}
return $this->_getCreateTableSQL($tableName, $columns, $options);
}
/**
* @param string $tableName
* @param array $columns
* @param array $options
* @return array
*/
protected function _getCreateTableSQL($tableName, array $columns, array $options = array())
{
$columnListSql = $this->getColumnDeclarationListSQL($columns);
if (isset($options['uniqueConstraints']) && ! empty($options['uniqueConstraints'])) {
foreach ($options['uniqueConstraints'] as $name => $definition) {
$columnListSql .= ', ' . $this->getUniqueConstraintDeclarationSQL($name, $definition);
}
}
if (isset($options['primary']) && ! empty($options['primary'])) {
$columnListSql .= ', PRIMARY KEY(' . implode(', ', array_unique(array_values($options['primary']))) . ')';
}
if (isset($options['indexes']) && ! empty($options['indexes'])) {
foreach($options['indexes'] as $index => $definition) {
$columnListSql .= ', ' . $this->getIndexDeclarationSQL($index, $definition);
}
}
$query = 'CREATE TABLE ' . $tableName . ' (' . $columnListSql;
$check = $this->getCheckDeclarationSQL($columns);
if ( ! empty($check)) {
$query .= ', ' . $check;
}
$query .= ')';
$sql[] = $query;
if (isset($options['foreignKeys'])) {
foreach ((array) $options['foreignKeys'] AS $definition) {
$sql[] = $this->getCreateForeignKeySQL($definition, $tableName);
}
}
return $sql;
}
public function getCreateTemporaryTableSnippetSQL()
{
return "CREATE TEMPORARY TABLE";
}
/**
* Gets the SQL to create a sequence on this platform.
*
* @param \Doctrine\DBAL\Schema\Sequence $sequence
* @throws DBALException
*/
public function getCreateSequenceSQL(\Doctrine\DBAL\Schema\Sequence $sequence)
{
throw DBALException::notSupported(__METHOD__);
}
/**
* Gets the SQL to create a constraint on a table on this platform.
*
* @param Constraint $constraint
* @param string|Table $table
* @return string
*/
public function getCreateConstraintSQL(\Doctrine\DBAL\Schema\Constraint $constraint, $table)
{
if ($table instanceof \Doctrine\DBAL\Schema\Table) {
$table = $table->getName();
}
$query = 'ALTER TABLE ' . $table . ' ADD CONSTRAINT ' . $constraint->getName();
$columns = array();
foreach ($constraint->getColumns() as $column) {
$columns[] = $column;
}
$columnList = '('. implode(', ', $columns) . ')';
$referencesClause = '';
if ($constraint instanceof \Doctrine\DBAL\Schema\Index) {
if($constraint->isPrimary()) {
$query .= ' PRIMARY KEY';
} elseif ($constraint->isUnique()) {
$query .= ' UNIQUE';
} else {
throw new \InvalidArgumentException(
'Can only create primary or unique constraints, no common indexes with getCreateConstraintSQL().'
);
}
} else if ($constraint instanceof \Doctrine\DBAL\Schema\ForeignKeyConstraint) {
$query .= ' FOREIGN KEY';
$foreignColumns = array();
foreach ($constraint->getForeignColumns() AS $column) {
$foreignColumns[] = $column;
}
$referencesClause = ' REFERENCES '.$constraint->getForeignTableName(). ' ('.implode(', ', $foreignColumns).')';
}
$query .= ' '.$columnList.$referencesClause;
return $query;
}
/**
* Gets the SQL to create an index on a table on this platform.
*
* @param Index $index
* @param string|Table $table name of the table on which the index is to be created
* @return string
*/
public function getCreateIndexSQL(Index $index, $table)
{
if ($table instanceof Table) {
$table = $table->getName();
}
$name = $index->getName();
$columns = $index->getColumns();
if (count($columns) == 0) {
throw new \InvalidArgumentException("Incomplete definition. 'columns' required.");
}
$type = '';
if ($index->isUnique()) {
$type = 'UNIQUE ';
}
$query = 'CREATE ' . $type . 'INDEX ' . $name . ' ON ' . $table;
$query .= ' (' . $this->getIndexFieldDeclarationListSQL($columns) . ')';
return $query;
}
/**
* Quotes a string so that it can be safely used as a table or column name,
* even if it is a reserved word of the platform.
*
* NOTE: Just because you CAN use quoted identifiers doesn't mean
* you SHOULD use them. In general, they end up causing way more
* problems than they solve.
*
* @param string $str identifier name to be quoted
* @return string quoted identifier string
*/
public function quoteIdentifier($str)
{
$c = $this->getIdentifierQuoteCharacter();
return $c . $str . $c;
}
/**
* Create a new foreign key
*
* @param ForeignKeyConstraint $foreignKey ForeignKey instance
* @param string|Table $table name of the table on which the foreign key is to be created
* @return string
*/
public function getCreateForeignKeySQL(ForeignKeyConstraint $foreignKey, $table)
{
if ($table instanceof \Doctrine\DBAL\Schema\Table) {
$table = $table->getName();
}
$query = 'ALTER TABLE ' . $table . ' ADD ' . $this->getForeignKeyDeclarationSQL($foreignKey);
return $query;
}
/**
* Gets the sql statements for altering an existing table.
*
* The method returns an array of sql statements, since some platforms need several statements.
*
* @param TableDiff $diff
* @return array
*/
public function getAlterTableSQL(TableDiff $diff)
{
throw DBALException::notSupported(__METHOD__);
}
/**
* Common code for alter table statement generation that updates the changed Index and Foreign Key definitions.
*
* @param TableDiff $diff
* @return array
*/
protected function _getAlterTableIndexForeignKeySQL(TableDiff $diff)
{
if ($diff->newName !== false) {
$tableName = $diff->newName;
} else {
$tableName = $diff->name;
}
$sql = array();
if ($this->supportsForeignKeyConstraints()) {
foreach ($diff->removedForeignKeys AS $foreignKey) {
$sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName);
}
foreach ($diff->addedForeignKeys AS $foreignKey) {
$sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName);
}
foreach ($diff->changedForeignKeys AS $foreignKey) {
$sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName);
$sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName);
}
}
foreach ($diff->addedIndexes AS $index) {
$sql[] = $this->getCreateIndexSQL($index, $tableName);
}
foreach ($diff->removedIndexes AS $index) {
$sql[] = $this->getDropIndexSQL($index, $tableName);
}
foreach ($diff->changedIndexes AS $index) {
$sql[] = $this->getDropIndexSQL($index, $tableName);
$sql[] = $this->getCreateIndexSQL($index, $tableName);
}
return $sql;
}
/**
* Get declaration of a number of fields in bulk
*
* @param array $fields a multidimensional associative array.
* The first dimension determines the field name, while the second
* dimension is keyed with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* length
* Integer value that determines the maximum length of the text
* field. If this argument is missing the field should be
* declared to have the longest length allowed by the DBMS.
*
* default
* Text value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to null.
* charset
* Text value with the default CHARACTER SET for this field.
* collation
* Text value with the default COLLATION for this field.
* unique
* unique constraint
*
* @return string
*/
public function getColumnDeclarationListSQL(array $fields)
{
$queryFields = array();
foreach ($fields as $fieldName => $field) {
$query = $this->getColumnDeclarationSQL($fieldName, $field);
$queryFields[] = $query;
}
return implode(', ', $queryFields);
}
/**
* Obtain DBMS specific SQL code portion needed to declare a generic type
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param array $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* length
* Integer value that determines the maximum length of the text
* field. If this argument is missing the field should be
* declared to have the longest length allowed by the DBMS.
*
* default
* Text value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to null.
* charset
* Text value with the default CHARACTER SET for this field.
* collation
* Text value with the default COLLATION for this field.
* unique
* unique constraint
* check
* column check constraint
* columnDefinition
* a string that defines the complete column
*
* @return string DBMS specific SQL code portion that should be used to declare the column.
*/
public function getColumnDeclarationSQL($name, array $field)
{
if (isset($field['columnDefinition'])) {
$columnDef = $this->getCustomTypeDeclarationSQL($field);
} else {
$default = $this->getDefaultValueDeclarationSQL($field);
$charset = (isset($field['charset']) && $field['charset']) ?
' ' . $this->getColumnCharsetDeclarationSQL($field['charset']) : '';
$collation = (isset($field['collation']) && $field['collation']) ?
' ' . $this->getColumnCollationDeclarationSQL($field['collation']) : '';
$notnull = (isset($field['notnull']) && $field['notnull']) ? ' NOT NULL' : '';
$unique = (isset($field['unique']) && $field['unique']) ?
' ' . $this->getUniqueFieldDeclarationSQL() : '';
$check = (isset($field['check']) && $field['check']) ?
' ' . $field['check'] : '';
$typeDecl = $field['type']->getSqlDeclaration($field, $this);
$columnDef = $typeDecl . $charset . $default . $notnull . $unique . $check . $collation;
}
return $name . ' ' . $columnDef;
}
/**
* Gets the SQL snippet that declares a floating point column of arbitrary precision.
*
* @param array $columnDef
* @return string
*/
public function getDecimalTypeDeclarationSQL(array $columnDef)
{
$columnDef['precision'] = ( ! isset($columnDef['precision']) || empty($columnDef['precision']))
? 10 : $columnDef['precision'];
$columnDef['scale'] = ( ! isset($columnDef['scale']) || empty($columnDef['scale']))
? 0 : $columnDef['scale'];
return 'NUMERIC(' . $columnDef['precision'] . ', ' . $columnDef['scale'] . ')';
}
/**
* Obtain DBMS specific SQL code portion needed to set a default value
* declaration to be used in statements like CREATE TABLE.
*
* @param array $field field definition array
* @return string DBMS specific SQL code portion needed to set a default value
*/
public function getDefaultValueDeclarationSQL($field)
{
$default = empty($field['notnull']) ? ' DEFAULT NULL' : '';
if (isset($field['default'])) {
$default = " DEFAULT '".$field['default']."'";
if (isset($field['type'])) {
if (in_array((string)$field['type'], array("Integer", "BigInteger", "SmallInteger"))) {
$default = " DEFAULT ".$field['default'];
} else if ((string)$field['type'] == 'DateTime' && $field['default'] == $this->getCurrentTimestampSQL()) {
$default = " DEFAULT ".$this->getCurrentTimestampSQL();
}
}
}
return $default;
}
/**
* Obtain DBMS specific SQL code portion needed to set a CHECK constraint
* declaration to be used in statements like CREATE TABLE.
*
* @param array $definition check definition
* @return string DBMS specific SQL code portion needed to set a CHECK constraint
*/
public function getCheckDeclarationSQL(array $definition)
{
$constraints = array();
foreach ($definition as $field => $def) {
if (is_string($def)) {
$constraints[] = 'CHECK (' . $def . ')';
} else {
if (isset($def['min'])) {
$constraints[] = 'CHECK (' . $field . ' >= ' . $def['min'] . ')';
}
if (isset($def['max'])) {
$constraints[] = 'CHECK (' . $field . ' <= ' . $def['max'] . ')';
}
}
}
return implode(', ', $constraints);
}
/**
* Obtain DBMS specific SQL code portion needed to set a unique
* constraint declaration to be used in statements like CREATE TABLE.
*
* @param string $name name of the unique constraint
* @param Index $index index definition
* @return string DBMS specific SQL code portion needed
* to set a constraint
*/
public function getUniqueConstraintDeclarationSQL($name, Index $index)
{
if (count($index->getColumns()) == 0) {
throw \InvalidArgumentException("Incomplete definition. 'columns' required.");
}
return 'CONSTRAINT ' . $name . ' UNIQUE ('
. $this->getIndexFieldDeclarationListSQL($index->getColumns())
. ')';
}
/**
* Obtain DBMS specific SQL code portion needed to set an index
* declaration to be used in statements like CREATE TABLE.
*
* @param string $name name of the index
* @param Index $index index definition
* @return string DBMS specific SQL code portion needed to set an index
*/
public function getIndexDeclarationSQL($name, Index $index)
{
$type = '';
if($index->isUnique()) {
$type = 'UNIQUE ';
}
if (count($index->getColumns()) == 0) {
throw \InvalidArgumentException("Incomplete definition. 'columns' required.");
}
return $type . 'INDEX ' . $name . ' ('
. $this->getIndexFieldDeclarationListSQL($index->getColumns())
. ')';
}
/**
* getCustomTypeDeclarationSql
* Obtail SQL code portion needed to create a custom column,
* e.g. when a field has the "columnDefinition" keyword.
* Only "AUTOINCREMENT" and "PRIMARY KEY" are added if appropriate.
*
* @return string
*/
public function getCustomTypeDeclarationSQL(array $columnDef)
{
return $columnDef['columnDefinition'];
}
/**
* getIndexFieldDeclarationList
* Obtain DBMS specific SQL code portion needed to set an index
* declaration to be used in statements like CREATE TABLE.
*
* @return string
*/
public function getIndexFieldDeclarationListSQL(array $fields)
{
$ret = array();
foreach ($fields as $field => $definition) {
if (is_array($definition)) {
$ret[] = $field;
} else {
$ret[] = $definition;
}
}
return implode(', ', $ret);
}
/**
* A method to return the required SQL string that fits between CREATE ... TABLE
* to create the table as a temporary table.
*
* Should be overridden in driver classes to return the correct string for the
* specific database type.
*
* The default is to return the string "TEMPORARY" - this will result in a
* SQL error for any database that does not support temporary tables, or that
* requires a different SQL command from "CREATE TEMPORARY TABLE".
*
* @return string The string required to be placed between "CREATE" and "TABLE"
* to generate a temporary table, if possible.
*/
public function getTemporaryTableSQL()
{
return 'TEMPORARY';
}
/**
* Some vendors require temporary table names to be qualified specially.
*
* @param string $tableName
* @return string
*/
public function getTemporaryTableName($tableName)
{
return $tableName;
}
/**
* Get sql query to show a list of database.
*
* @return string
*/
public function getShowDatabasesSQL()
{
throw DBALException::notSupported(__METHOD__);
}
/**
* Obtain DBMS specific SQL code portion needed to set the FOREIGN KEY constraint
* of a field declaration to be used in statements like CREATE TABLE.
*
* @param array $definition an associative array with the following structure:
* name optional constraint name
*
* local the local field(s)
*
* foreign the foreign reference field(s)
*
* foreignTable the name of the foreign table
*
* onDelete referential delete action
*
* onUpdate referential update action
*
* deferred deferred constraint checking
*
* The onDelete and onUpdate keys accept the following values:
*
* CASCADE: Delete or update the row from the parent table and automatically delete or
* update the matching rows in the child table. Both ON DELETE CASCADE and ON UPDATE CASCADE are supported.
* Between two tables, you should not define several ON UPDATE CASCADE clauses that act on the same column
* in the parent table or in the child table.
*
* SET NULL: Delete or update the row from the parent table and set the foreign key column or columns in the
* child table to NULL. This is valid only if the foreign key columns do not have the NOT NULL qualifier
* specified. Both ON DELETE SET NULL and ON UPDATE SET NULL clauses are supported.
*
* NO ACTION: In standard SQL, NO ACTION means no action in the sense that an attempt to delete or update a primary
* key value is not allowed to proceed if there is a related foreign key value in the referenced table.
*
* RESTRICT: Rejects the delete or update operation for the parent table. NO ACTION and RESTRICT are the same as
* omitting the ON DELETE or ON UPDATE clause.
*
* SET DEFAULT
*
* @return string DBMS specific SQL code portion needed to set the FOREIGN KEY constraint
* of a field declaration.
*/
public function getForeignKeyDeclarationSQL(ForeignKeyConstraint $foreignKey)
{
$sql = $this->getForeignKeyBaseDeclarationSQL($foreignKey);
$sql .= $this->getAdvancedForeignKeyOptionsSQL($foreignKey);
return $sql;
}
/**
* Return the FOREIGN KEY query section dealing with non-standard options
* as MATCH, INITIALLY DEFERRED, ON UPDATE, ...
*
* @param ForeignKeyConstraint $foreignKey foreign key definition
* @return string
*/
public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey)
{
$query = '';
if ($this->supportsForeignKeyOnUpdate() && $foreignKey->hasOption('onUpdate')) {
$query .= ' ON UPDATE ' . $this->getForeignKeyReferentialActionSQL($foreignKey->getOption('onUpdate'));
}
if ($foreignKey->hasOption('onDelete')) {
$query .= ' ON DELETE ' . $this->getForeignKeyReferentialActionSQL($foreignKey->getOption('onDelete'));
}
return $query;
}
/**
* returns given referential action in uppercase if valid, otherwise throws
* an exception
*
* @throws Doctrine_Exception_Exception if unknown referential action given
* @param string $action foreign key referential action
* @param string foreign key referential action in uppercase
*/
public function getForeignKeyReferentialActionSQL($action)
{
$upper = strtoupper($action);
switch ($upper) {
case 'CASCADE':
case 'SET NULL':
case 'NO ACTION':
case 'RESTRICT':
case 'SET DEFAULT':
return $upper;
break;
default:
throw \InvalidArgumentException('Invalid foreign key action: ' . $upper);
}
}
/**
* Obtain DBMS specific SQL code portion needed to set the FOREIGN KEY constraint
* of a field declaration to be used in statements like CREATE TABLE.
*
* @param ForeignKeyConstraint $foreignKey
* @return string
*/
public function getForeignKeyBaseDeclarationSQL(ForeignKeyConstraint $foreignKey)
{
$sql = '';
if (strlen($foreignKey->getName())) {
$sql .= 'CONSTRAINT ' . $foreignKey->getName() . ' ';
}
$sql .= 'FOREIGN KEY (';
if (count($foreignKey->getLocalColumns()) == 0) {
throw new \InvalidArgumentException("Incomplete definition. 'local' required.");
}
if (count($foreignKey->getForeignColumns()) == 0) {
throw new \InvalidArgumentException("Incomplete definition. 'foreign' required.");
}
if (strlen($foreignKey->getForeignTableName()) == 0) {
throw new \InvalidArgumentException("Incomplete definition. 'foreignTable' required.");
}
$sql .= implode(', ', $foreignKey->getLocalColumns())
. ') REFERENCES '
. $foreignKey->getForeignTableName() . '('
. implode(', ', $foreignKey->getForeignColumns()) . ')';
return $sql;
}
/**
* Obtain DBMS specific SQL code portion needed to set the UNIQUE constraint
* of a field declaration to be used in statements like CREATE TABLE.
*
* @return string DBMS specific SQL code portion needed to set the UNIQUE constraint
* of a field declaration.
*/
public function getUniqueFieldDeclarationSQL()
{
return 'UNIQUE';
}
/**
* Obtain DBMS specific SQL code portion needed to set the CHARACTER SET
* of a field declaration to be used in statements like CREATE TABLE.
*
* @param string $charset name of the charset
* @return string DBMS specific SQL code portion needed to set the CHARACTER SET
* of a field declaration.
*/
public function getColumnCharsetDeclarationSQL($charset)
{
return '';
}
/**
* Obtain DBMS specific SQL code portion needed to set the COLLATION
* of a field declaration to be used in statements like CREATE TABLE.
*
* @param string $collation name of the collation
* @return string DBMS specific SQL code portion needed to set the COLLATION
* of a field declaration.
*/
public function getColumnCollationDeclarationSQL($collation)
{
return '';
}
/**
* Whether the platform prefers sequences for ID generation.
* Subclasses should override this method to return TRUE if they prefer sequences.
*
* @return boolean
*/
public function prefersSequences()
{
return false;
}
/**
* Whether the platform prefers identity columns (eg. autoincrement) for ID generation.
* Subclasses should override this method to return TRUE if they prefer identity columns.
*
* @return boolean
*/
public function prefersIdentityColumns()
{
return false;
}
/**
* Some platforms need the boolean values to be converted.
*
* The default conversion in this implementation converts to integers (false => 0, true => 1).
*
* @param mixed $item
*/
public function convertBooleans($item)
{
if (is_array($item)) {
foreach ($item as $k => $value) {
if (is_bool($value)) {
$item[$k] = (int) $value;
}
}
} else if (is_bool($item)) {
$item = (int) $item;
}
return $item;
}
/**
* Gets the SQL statement specific for the platform to set the charset.
*
* This function is MySQL specific and required by
* {@see \Doctrine\DBAL\Connection::setCharset($charset)}
*
* @param string $charset
* @return string
*/
public function getSetCharsetSQL($charset)
{
return "SET NAMES '".$charset."'";
}
/**
* Gets the SQL specific for the platform to get the current date.
*
* @return string
*/
public function getCurrentDateSQL()
{
return 'CURRENT_DATE';
}
/**
* Gets the SQL specific for the platform to get the current time.
*
* @return string
*/
public function getCurrentTimeSQL()
{
return 'CURRENT_TIME';
}
/**
* Gets the SQL specific for the platform to get the current timestamp
*
* @return string
*/
public function getCurrentTimestampSQL()
{
return 'CURRENT_TIMESTAMP';
}
/**
* Get sql for transaction isolation level Connection constant
*
* @param integer $level
*/
protected function _getTransactionIsolationLevelSQL($level)
{
switch ($level) {
case Connection::TRANSACTION_READ_UNCOMMITTED:
return 'READ UNCOMMITTED';
case Connection::TRANSACTION_READ_COMMITTED:
return 'READ COMMITTED';
case Connection::TRANSACTION_REPEATABLE_READ:
return 'REPEATABLE READ';
case Connection::TRANSACTION_SERIALIZABLE:
return 'SERIALIZABLE';
default:
throw new \InvalidArgumentException('Invalid isolation level:' . $level);
}
}
public function getListDatabasesSQL()
{
throw DBALException::notSupported(__METHOD__);
}
public function getListSequencesSQL($database)
{
throw DBALException::notSupported(__METHOD__);
}
public function getListTableConstraintsSQL($table)
{
throw DBALException::notSupported(__METHOD__);
}
public function getListTableColumnsSQL($table)
{
throw DBALException::notSupported(__METHOD__);
}
public function getListTablesSQL()
{
throw DBALException::notSupported(__METHOD__);
}
public function getListUsersSQL()
{
throw DBALException::notSupported(__METHOD__);
}
/**
* Get the SQL to list all views of a database or user.
*
* @param string $database
* @return string
*/
public function getListViewsSQL($database)
{
throw DBALException::notSupported(__METHOD__);
}
public function getListTableIndexesSQL($table)
{
throw DBALException::notSupported(__METHOD__);
}
public function getListTableForeignKeysSQL($table)
{
throw DBALException::notSupported(__METHOD__);
}
public function getCreateViewSQL($name, $sql)
{
throw DBALException::notSupported(__METHOD__);
}
public function getDropViewSQL($name)
{
throw DBALException::notSupported(__METHOD__);
}
public function getDropSequenceSQL($sequence)
{
throw DBALException::notSupported(__METHOD__);
}
public function getSequenceNextValSQL($sequenceName)
{
throw DBALException::notSupported(__METHOD__);
}
public function getCreateDatabaseSQL($database)
{
throw DBALException::notSupported(__METHOD__);
}
/**
* Get sql to set the transaction isolation level
*
* @param integer $level
*/
public function getSetTransactionIsolationSQL($level)
{
throw DBALException::notSupported(__METHOD__);
}
/**
* Obtain DBMS specific SQL to be used to create datetime fields in
* statements like CREATE TABLE
*
* @param array $fieldDeclaration
* @return string
*/
public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
{
throw DBALException::notSupported(__METHOD__);
}
/**
* Obtain DBMS specific SQL to be used to create datetime with timezone offset fields.
*
* @param array $fieldDeclaration
*/
public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration)
{
return $this->getDateTimeTypeDeclarationSQL($fieldDeclaration);
}
/**
* Obtain DBMS specific SQL to be used to create date fields in statements
* like CREATE TABLE.
*
* @param array $fieldDeclaration
* @return string
*/
public function getDateTypeDeclarationSQL(array $fieldDeclaration)
{
throw DBALException::notSupported(__METHOD__);
}
/**
* Obtain DBMS specific SQL to be used to create time fields in statements
* like CREATE TABLE.
*
* @param array $fieldDeclaration
* @return string
*/
public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
{
throw DBALException::notSupported(__METHOD__);
}
public function getFloatDeclarationSQL(array $fieldDeclaration)
{
return 'DOUBLE PRECISION';
}
/**
* Gets the default transaction isolation level of the platform.
*
* @return integer The default isolation level.
* @see Doctrine\DBAL\Connection\TRANSACTION_* constants.
*/
public function getDefaultTransactionIsolationLevel()
{
return Connection::TRANSACTION_READ_COMMITTED;
}
/* supports*() metods */
/**
* Whether the platform supports sequences.
*
* @return boolean
*/
public function supportsSequences()
{
return false;
}
/**
* Whether the platform supports identity columns.
* Identity columns are columns that recieve an auto-generated value from the
* database on insert of a row.
*
* @return boolean
*/
public function supportsIdentityColumns()
{
return false;
}
/**
* Whether the platform supports indexes.
*
* @return boolean
*/
public function supportsIndexes()
{
return true;
}
public function supportsAlterTable()
{
return true;
}
/**
* Whether the platform supports transactions.
*
* @return boolean
*/
public function supportsTransactions()
{
return true;
}
/**
* Whether the platform supports savepoints.
*
* @return boolean
*/
public function supportsSavepoints()
{
return true;
}
/**
* Whether the platform supports releasing savepoints.
*
* @return boolean
*/
public function supportsReleaseSavepoints()
{
return $this->supportsSavepoints();
}
/**
* Whether the platform supports primary key constraints.
*
* @return boolean
*/
public function supportsPrimaryConstraints()
{
return true;
}
/**
* Does the platform supports foreign key constraints?
*
* @return boolean
*/
public function supportsForeignKeyConstraints()
{
return true;
}
/**
* Does this platform supports onUpdate in foreign key constraints?
*
* @return bool
*/
public function supportsForeignKeyOnUpdate()
{
return ($this->supportsForeignKeyConstraints() && true);
}
/**
* Whether the platform supports database schemas.
*
* @return boolean
*/
public function supportsSchemas()
{
return false;
}
/**
* Some databases don't allow to create and drop databases at all or only with certain tools.
*
* @return bool
*/
public function supportsCreateDropDatabase()
{
return true;
}
/**
* Whether the platform supports getting the affected rows of a recent
* update/delete type query.
*
* @return boolean
*/
public function supportsGettingAffectedRows()
{
return true;
}
public function getIdentityColumnNullInsertSQL()
{
return "";
}
/**
* Gets the format string, as accepted by the date() function, that describes
* the format of a stored datetime value of this platform.
*
* @return string The format string.
*/
public function getDateTimeFormatString()
{
return 'Y-m-d H:i:s';
}
/**
* Gets the format string, as accepted by the date() function, that describes
* the format of a stored datetime with timezone value of this platform.
*
* @return string The format string.
*/
public function getDateTimeTzFormatString()
{
return 'Y-m-d H:i:s';
}
/**
* Gets the format string, as accepted by the date() function, that describes
* the format of a stored date value of this platform.
*
* @return string The format string.
*/
public function getDateFormatString()
{
return 'Y-m-d';
}
/**
* Gets the format string, as accepted by the date() function, that describes
* the format of a stored time value of this platform.
*
* @return string The format string.
*/
public function getTimeFormatString()
{
return 'H:i:s';
}
public function modifyLimitQuery($query, $limit, $offset = null)
{
if ( ! is_null($limit)) {
$query .= ' LIMIT ' . $limit;
}
if ( ! is_null($offset)) {
$query .= ' OFFSET ' . $offset;
}
return $query;
}
/**
* Gets the character casing of a column in an SQL result set of this platform.
*
* @param string $column The column name for which to get the correct character casing.
* @return string The column name in the character casing used in SQL result sets.
*/
public function getSQLResultCasing($column)
{
return $column;
}
/**
* Makes any fixes to a name of a schema element (table, sequence, ...) that are required
* by restrictions of the platform, like a maximum length.
*
* @param string $schemaName
* @return string
*/
public function fixSchemaElementName($schemaElementName)
{
return $schemaElementName;
}
/**
* Maximum length of any given databse identifier, like tables or column names.
*
* @return int
*/
public function getMaxIdentifierLength()
{
return 63;
}
/**
* Get the insert sql for an empty insert statement
*
* @param string $tableName
* @param string $identifierColumnName
* @return string $sql
*/
public function getEmptyIdentityInsertSQL($tableName, $identifierColumnName)
{
return 'INSERT INTO ' . $tableName . ' (' . $identifierColumnName . ') VALUES (null)';
}
/**
* Generate a Truncate Table SQL statement for a given table.
*
* Cascade is not supported on many platforms but would optionally cascade the truncate by
* following the foreign keys.
*
* @param string $tableName
* @param bool $cascade
* @return string
*/
public function getTruncateTableSQL($tableName, $cascade = false)
{
return 'TRUNCATE '.$tableName;
}
/**
* This is for test reasons, many vendors have special requirements for dummy statements.
*
* @return string
*/
public function getDummySelectSQL()
{
return 'SELECT 1';
}
/**
* Generate SQL to create a new savepoint
*
* @param string $savepoint
* @return string
*/
public function createSavePoint($savepoint)
{
return 'SAVEPOINT ' . $savepoint;
}
/**
* Generate SQL to release a savepoint
*
* @param string $savepoint
* @return string
*/
public function releaseSavePoint($savepoint)
{
return 'RELEASE SAVEPOINT ' . $savepoint;
}
/**
* Generate SQL to rollback a savepoint
*
* @param string $savepoint
* @return string
*/
public function rollbackSavePoint($savepoint)
{
return 'ROLLBACK TO SAVEPOINT ' . $savepoint;
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms;
use Doctrine\DBAL\DBALException;
/**
* The SqlitePlatform class describes the specifics and dialects of the SQLite
* database platform.
*
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @todo Rename: SQLitePlatform
*/
class SqlitePlatform extends AbstractPlatform
{
/**
* returns the regular expression operator
*
* @return string
* @override
*/
public function getRegexpExpression()
{
return 'RLIKE';
}
/**
* Return string to call a variable with the current timestamp inside an SQL statement
* There are three special variables for current date and time.
*
* @return string sqlite function as string
* @override
*/
public function getNowExpression($type = 'timestamp')
{
switch ($type) {
case 'time':
return 'time(\'now\')';
case 'date':
return 'date(\'now\')';
case 'timestamp':
default:
return 'datetime(\'now\')';
}
}
/**
* Trim a string, leading/trailing/both and with a given char which defaults to space.
*
* @param string $str
* @param int $pos
* @param string $char
* @return string
*/
public function getTrimExpression($str, $pos = self::TRIM_UNSPECIFIED, $char = false)
{
$trimFn = '';
$trimChar = ($char != false) ? (', ' . $char) : '';
if ($pos == self::TRIM_LEADING) {
$trimFn = 'LTRIM';
} else if($pos == self::TRIM_TRAILING) {
$trimFn = 'RTRIM';
} else {
$trimFn = 'TRIM';
}
return $trimFn . '(' . $str . $trimChar . ')';
}
/**
* return string to call a function to get a substring inside an SQL statement
*
* Note: Not SQL92, but common functionality.
*
* SQLite only supports the 2 parameter variant of this function
*
* @param string $value an sql string literal or column name/alias
* @param integer $position where to start the substring portion
* @param integer $length the substring portion length
* @return string SQL substring function with given parameters
* @override
*/
public function getSubstringExpression($value, $position, $length = null)
{
if ($length !== null) {
return 'SUBSTR(' . $value . ', ' . $position . ', ' . $length . ')';
}
return 'SUBSTR(' . $value . ', ' . $position . ', LENGTH(' . $value . '))';
}
/**
* returns the position of the first occurrence of substring $substr in string $str
*
* @param string $substr literal string to find
* @param string $str literal string
* @param int $pos position to start at, beginning of string by default
* @return integer
*/
public function getLocateExpression($str, $substr, $startPos = false)
{
if ($startPos == false) {
return 'LOCATE('.$str.', '.$substr.')';
} else {
return 'LOCATE('.$str.', '.$substr.', '.$startPos.')';
}
}
protected function _getTransactionIsolationLevelSQL($level)
{
switch ($level) {
case \Doctrine\DBAL\Connection::TRANSACTION_READ_UNCOMMITTED:
return 0;
case \Doctrine\DBAL\Connection::TRANSACTION_READ_COMMITTED:
case \Doctrine\DBAL\Connection::TRANSACTION_REPEATABLE_READ:
case \Doctrine\DBAL\Connection::TRANSACTION_SERIALIZABLE:
return 1;
default:
return parent::_getTransactionIsolationLevelSQL($level);
}
}
public function getSetTransactionIsolationSQL($level)
{
return 'PRAGMA read_uncommitted = ' . $this->_getTransactionIsolationLevelSQL($level);
}
/**
* @override
*/
public function prefersIdentityColumns()
{
return true;
}
/**
* @override
*/
public function getBooleanTypeDeclarationSQL(array $field)
{
return 'BOOLEAN';
}
/**
* @override
*/
public function getIntegerTypeDeclarationSQL(array $field)
{
return $this->_getCommonIntegerTypeDeclarationSQL($field);
}
/**
* @override
*/
public function getBigIntTypeDeclarationSQL(array $field)
{
return $this->_getCommonIntegerTypeDeclarationSQL($field);
}
/**
* @override
*/
public function getTinyIntTypeDeclarationSql(array $field)
{
return $this->_getCommonIntegerTypeDeclarationSQL($field);
}
/**
* @override
*/
public function getSmallIntTypeDeclarationSQL(array $field)
{
return $this->_getCommonIntegerTypeDeclarationSQL($field);
}
/**
* @override
*/
public function getMediumIntTypeDeclarationSql(array $field)
{
return $this->_getCommonIntegerTypeDeclarationSQL($field);
}
/**
* @override
*/
public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
{
return 'DATETIME';
}
/**
* @override
*/
public function getDateTypeDeclarationSQL(array $fieldDeclaration)
{
return 'DATE';
}
/**
* @override
*/
public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
{
return 'TIME';
}
/**
* @override
*/
protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef)
{
$autoinc = ! empty($columnDef['autoincrement']) ? ' AUTOINCREMENT' : '';
$pk = ! empty($columnDef['primary']) && ! empty($autoinc) ? ' PRIMARY KEY' : '';
return 'INTEGER' . $pk . $autoinc;
}
/**
* create a new table
*
* @param string $name Name of the database that should be created
* @param array $fields Associative array that contains the definition of each field of the new table
* The indexes of the array entries are the names of the fields of the table an
* the array entry values are associative arrays like those that are meant to be
* passed with the field definitions to get[Type]Declaration() functions.
* array(
* 'id' => array(
* 'type' => 'integer',
* 'unsigned' => 1
* 'notnull' => 1
* 'default' => 0
* ),
* 'name' => array(
* 'type' => 'text',
* 'length' => 12
* ),
* 'password' => array(
* 'type' => 'text',
* 'length' => 12
* )
* );
* @param array $options An associative array of table options:
*
* @return void
* @override
*/
protected function _getCreateTableSQL($name, array $columns, array $options = array())
{
$queryFields = $this->getColumnDeclarationListSQL($columns);
$autoinc = false;
foreach($columns as $field) {
if (isset($field['autoincrement']) && $field['autoincrement']) {
$autoinc = true;
break;
}
}
if ( ! $autoinc && isset($options['primary']) && ! empty($options['primary'])) {
$keyColumns = array_unique(array_values($options['primary']));
$keyColumns = array_map(array($this, 'quoteIdentifier'), $keyColumns);
$queryFields.= ', PRIMARY KEY('.implode(', ', $keyColumns).')';
}
$query[] = 'CREATE TABLE ' . $name . ' (' . $queryFields . ')';
if (isset($options['indexes']) && ! empty($options['indexes'])) {
foreach ($options['indexes'] as $index => $indexDef) {
$query[] = $this->getCreateIndexSQL($indexDef, $name);
}
}
if (isset($options['unique']) && ! empty($options['unique'])) {
foreach ($options['unique'] as $index => $indexDef) {
$query[] = $this->getCreateIndexSQL($indexDef, $name);
}
}
return $query;
}
/**
* {@inheritdoc}
*/
public function getVarcharTypeDeclarationSQL(array $field)
{
if ( ! isset($field['length'])) {
if (array_key_exists('default', $field)) {
$field['length'] = $this->getVarcharMaxLength();
} else {
$field['length'] = false;
}
}
$length = ($field['length'] <= $this->getVarcharMaxLength()) ? $field['length'] : false;
$fixed = (isset($field['fixed'])) ? $field['fixed'] : false;
return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)')
: ($length ? 'VARCHAR(' . $length . ')' : 'TEXT');
}
public function getClobTypeDeclarationSQL(array $field)
{
return 'CLOB';
}
public function getListTableConstraintsSQL($table)
{
return "SELECT sql FROM sqlite_master WHERE type='index' AND tbl_name = '$table' AND sql NOT NULL ORDER BY name";
}
public function getListTableColumnsSQL($table)
{
return "PRAGMA table_info($table)";
}
public function getListTableIndexesSQL($table)
{
return "PRAGMA index_list($table)";
}
public function getListTablesSQL()
{
return "SELECT name FROM sqlite_master WHERE type = 'table' AND name != 'sqlite_sequence' "
. "UNION ALL SELECT name FROM sqlite_temp_master "
. "WHERE type = 'table' ORDER BY name";
}
public function getListViewsSQL($database)
{
return "SELECT name, sql FROM sqlite_master WHERE type='view' AND sql NOT NULL";
}
public function getCreateViewSQL($name, $sql)
{
return 'CREATE VIEW ' . $name . ' AS ' . $sql;
}
public function getDropViewSQL($name)
{
return 'DROP VIEW '. $name;
}
/**
* SQLite does support foreign key constraints, but only in CREATE TABLE statements...
* This really limits their usefulness and requires SQLite specific handling, so
* we simply say that SQLite does NOT support foreign keys for now...
*
* @return boolean FALSE
* @override
*/
public function supportsForeignKeyConstraints()
{
return false;
}
public function supportsAlterTable()
{
return false;
}
public function supportsIdentityColumns()
{
return true;
}
/**
* Get the platform name for this instance
*
* @return string
*/
public function getName()
{
return 'sqlite';
}
/**
* @inheritdoc
*/
public function getTruncateTableSQL($tableName, $cascade = false)
{
return 'DELETE FROM '.$tableName;
}
/**
* User-defined function for Sqlite that is used with PDO::sqliteCreateFunction()
*
* @param int|float $value
* @return float
*/
static public function udfSqrt($value)
{
return sqrt($value);
}
/**
* User-defined function for Sqlite that implements MOD(a, b)
*/
static public function udfMod($a, $b)
{
return ($a % $b);
}
/**
* @param string $str
* @param string $substr
* @param int $offset
*/
static public function udfLocate($str, $substr, $offset = 0)
{
$pos = strpos($str, $substr, $offset);
if ($pos !== false) {
return $pos+1;
}
return 0;
}
public function getForUpdateSql()
{
return '';
}
protected function initializeDoctrineTypeMappings()
{
$this->doctrineTypeMapping = array(
'boolean' => 'boolean',
'tinyint' => 'boolean',
'smallint' => 'smallint',
'mediumint' => 'integer',
'int' => 'integer',
'integer' => 'integer',
'serial' => 'integer',
'bigint' => 'bigint',
'bigserial' => 'bigint',
'clob' => 'text',
'tinytext' => 'text',
'mediumtext' => 'text',
'longtext' => 'text',
'text' => 'text',
'varchar' => 'string',
'varchar2' => 'string',
'nvarchar' => 'string',
'image' => 'string',
'ntext' => 'string',
'char' => 'string',
'date' => 'date',
'datetime' => 'datetime',
'timestamp' => 'datetime',
'time' => 'time',
'float' => 'float',
'double' => 'float',
'real' => 'float',
'decimal' => 'decimal',
'numeric' => 'decimal',
);
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL;
/**
* Class to store and retrieve the version of Doctrine
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class Version
{
/**
* Current Doctrine Version
*/
const VERSION = '2.0.0RC1-DEV';
/**
* Compares a Doctrine version with the current one.
*
* @param string $version Doctrine version to compare.
* @return int Returns -1 if older, 0 if it is the same, 1 if version
* passed as argument is newer.
*/
public static function compare($version)
{
$currentVersion = str_replace(' ', '', strtolower(self::VERSION));
$version = str_replace(' ', '', $version);
return version_compare($version, $currentVersion);
}
}<?php
/*
* $Id: Exception.php 4628 2008-07-04 16:32:19Z romanb $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL;
/**
* Doctrine\DBAL\ConnectionException
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 4628 $
* @author Jonathan H. Wage <jonwage@gmail.com
*/
class ConnectionException extends DBALException
{
public static function commitFailedRollbackOnly()
{
return new self("Transaction commit failed because the transaction has been marked for rollback only.");
}
public static function noActiveTransaction()
{
return new self("There is no active transaction.");
}
public static function savepointsNotSupported()
{
return new self("Savepoints are not supported by this driver.");
}
public static function mayNotAlterNestedTransactionWithSavepointsInTransaction()
{
return new self("May not alter the nested transaction with savepoints behavior while a transaction is open.");
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL;
use PDO, Closure, Exception,
Doctrine\DBAL\Types\Type,
Doctrine\DBAL\Driver\Connection as DriverConnection,
Doctrine\Common\EventManager,
Doctrine\DBAL\DBALException;
/**
* A wrapper around a Doctrine\DBAL\Driver\Connection that adds features like
* events, transaction isolation levels, configuration, emulated transaction nesting,
* lazy connecting and more.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (MDB2 library)
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class Connection implements DriverConnection
{
/**
* Constant for transaction isolation level READ UNCOMMITTED.
*/
const TRANSACTION_READ_UNCOMMITTED = 1;
/**
* Constant for transaction isolation level READ COMMITTED.
*/
const TRANSACTION_READ_COMMITTED = 2;
/**
* Constant for transaction isolation level REPEATABLE READ.
*/
const TRANSACTION_REPEATABLE_READ = 3;
/**
* Constant for transaction isolation level SERIALIZABLE.
*/
const TRANSACTION_SERIALIZABLE = 4;
/**
* The wrapped driver connection.
*
* @var Doctrine\DBAL\Driver\Connection
*/
protected $_conn;
/**
* @var Doctrine\DBAL\Configuration
*/
protected $_config;
/**
* @var Doctrine\Common\EventManager
*/
protected $_eventManager;
/**
* Whether or not a connection has been established.
*
* @var boolean
*/
private $_isConnected = false;
/**
* The transaction nesting level.
*
* @var integer
*/
private $_transactionNestingLevel = 0;
/**
* The currently active transaction isolation level.
*
* @var integer
*/
private $_transactionIsolationLevel;
/**
* If nested transations should use savepoints
*
* @var integer
*/
private $_nestTransactionsWithSavepoints;
/**
* The parameters used during creation of the Connection instance.
*
* @var array
*/
private $_params = array();
/**
* The DatabasePlatform object that provides information about the
* database platform used by the connection.
*
* @var Doctrine\DBAL\Platforms\AbstractPlatform
*/
protected $_platform;
/**
* The schema manager.
*
* @var Doctrine\DBAL\Schema\SchemaManager
*/
protected $_schemaManager;
/**
* The used DBAL driver.
*
* @var Doctrine\DBAL\Driver
*/
protected $_driver;
/**
* Flag that indicates whether the current transaction is marked for rollback only.
*
* @var boolean
*/
private $_isRollbackOnly = false;
/**
* Initializes a new instance of the Connection class.
*
* @param array $params The connection parameters.
* @param Driver $driver
* @param Configuration $config
* @param EventManager $eventManager
*/
public function __construct(array $params, Driver $driver, Configuration $config = null,
EventManager $eventManager = null)
{
$this->_driver = $driver;
$this->_params = $params;
if (isset($params['pdo'])) {
$this->_conn = $params['pdo'];
$this->_isConnected = true;
}
// Create default config and event manager if none given
if ( ! $config) {
$config = new Configuration();
}
if ( ! $eventManager) {
$eventManager = new EventManager();
}
$this->_config = $config;
$this->_eventManager = $eventManager;
if ( ! isset($params['platform'])) {
$this->_platform = $driver->getDatabasePlatform();
} else if ($params['platform'] instanceof Platforms\AbstractPlatform) {
$this->_platform = $params['platform'];
} else {
throw DBALException::invalidPlatformSpecified();
}
$this->_transactionIsolationLevel = $this->_platform->getDefaultTransactionIsolationLevel();
}
/**
* Gets the parameters used during instantiation.
*
* @return array $params
*/
public function getParams()
{
return $this->_params;
}
/**
* Gets the name of the database this Connection is connected to.
*
* @return string $database
*/
public function getDatabase()
{
return $this->_driver->getDatabase($this);
}
/**
* Gets the hostname of the currently connected database.
*
* @return string
*/
public function getHost()
{
return isset($this->_params['host']) ? $this->_params['host'] : null;
}
/**
* Gets the port of the currently connected database.
*
* @return mixed
*/
public function getPort()
{
return isset($this->_params['port']) ? $this->_params['port'] : null;
}
/**
* Gets the username used by this connection.
*
* @return string
*/
public function getUsername()
{
return isset($this->_params['user']) ? $this->_params['user'] : null;
}
/**
* Gets the password used by this connection.
*
* @return string
*/
public function getPassword()
{
return isset($this->_params['password']) ? $this->_params['password'] : null;
}
/**
* Gets the DBAL driver instance.
*
* @return Doctrine\DBAL\Driver
*/
public function getDriver()
{
return $this->_driver;
}
/**
* Gets the Configuration used by the Connection.
*
* @return Doctrine\DBAL\Configuration
*/
public function getConfiguration()
{
return $this->_config;
}
/**
* Gets the EventManager used by the Connection.
*
* @return Doctrine\Common\EventManager
*/
public function getEventManager()
{
return $this->_eventManager;
}
/**
* Gets the DatabasePlatform for the connection.
*
* @return Doctrine\DBAL\Platforms\AbstractPlatform
*/
public function getDatabasePlatform()
{
return $this->_platform;
}
/**
* Establishes the connection with the database.
*
* @return boolean TRUE if the connection was successfully established, FALSE if
* the connection is already open.
*/
public function connect()
{
if ($this->_isConnected) return false;
$driverOptions = isset($this->_params['driverOptions']) ?
$this->_params['driverOptions'] : array();
$user = isset($this->_params['user']) ? $this->_params['user'] : null;
$password = isset($this->_params['password']) ?
$this->_params['password'] : null;
$this->_conn = $this->_driver->connect($this->_params, $user, $password, $driverOptions);
$this->_isConnected = true;
if ($this->_eventManager->hasListeners(Events::postConnect)) {
$eventArgs = new Event\ConnectionEventArgs($this);
$this->_eventManager->dispatchEvent(Events::postConnect, $eventArgs);
}
return true;
}
/**
* Prepares and executes an SQL query and returns the first row of the result
* as an associative array.
*
* @param string $statement The SQL query.
* @param array $params The query parameters.
* @return array
*/
public function fetchAssoc($statement, array $params = array())
{
return $this->executeQuery($statement, $params)->fetch(PDO::FETCH_ASSOC);
}
/**
* Prepares and executes an SQL query and returns the first row of the result
* as a numerically indexed array.
*
* @param string $statement sql query to be executed
* @param array $params prepared statement params
* @return array
*/
public function fetchArray($statement, array $params = array())
{
return $this->executeQuery($statement, $params)->fetch(PDO::FETCH_NUM);
}
/**
* Prepares and executes an SQL query and returns the value of a single column
* of the first row of the result.
*
* @param string $statement sql query to be executed
* @param array $params prepared statement params
* @param int $colnum 0-indexed column number to retrieve
* @return mixed
*/
public function fetchColumn($statement, array $params = array(), $colnum = 0)
{
return $this->executeQuery($statement, $params)->fetchColumn($colnum);
}
/**
* Whether an actual connection to the database is established.
*
* @return boolean
*/
public function isConnected()
{
return $this->_isConnected;
}
/**
* Checks whether a transaction is currently active.
*
* @return boolean TRUE if a transaction is currently active, FALSE otherwise.
*/
public function isTransactionActive()
{
return $this->_transactionNestingLevel > 0;
}
/**
* Executes an SQL DELETE statement on a table.
*
* @param string $table The name of the table on which to delete.
* @param array $identifier The deletion criteria. An associateve array containing column-value pairs.
* @return integer The number of affected rows.
*/
public function delete($tableName, array $identifier)
{
$this->connect();
$criteria = array();
foreach (array_keys($identifier) as $columnName) {
$criteria[] = $columnName . ' = ?';
}
$query = 'DELETE FROM ' . $tableName . ' WHERE ' . implode(' AND ', $criteria);
return $this->executeUpdate($query, array_values($identifier));
}
/**
* Closes the connection.
*
* @return void
*/
public function close()
{
unset($this->_conn);
$this->_isConnected = false;
}
/**
* Sets the transaction isolation level.
*
* @param integer $level The level to set.
*/
public function setTransactionIsolation($level)
{
$this->_transactionIsolationLevel = $level;
return $this->executeUpdate($this->_platform->getSetTransactionIsolationSQL($level));
}
/**
* Gets the currently active transaction isolation level.
*
* @return integer The current transaction isolation level.
*/
public function getTransactionIsolation()
{
return $this->_transactionIsolationLevel;
}
/**
* Executes an SQL UPDATE statement on a table.
*
* @param string $table The name of the table to update.
* @param array $identifier The update criteria. An associative array containing column-value pairs.
* @return integer The number of affected rows.
*/
public function update($tableName, array $data, array $identifier)
{
$this->connect();
$set = array();
foreach ($data as $columnName => $value) {
$set[] = $columnName . ' = ?';
}
$params = array_merge(array_values($data), array_values($identifier));
$sql = 'UPDATE ' . $tableName . ' SET ' . implode(', ', $set)
. ' WHERE ' . implode(' = ? AND ', array_keys($identifier))
. ' = ?';
return $this->executeUpdate($sql, $params);
}
/**
* Inserts a table row with specified data.
*
* @param string $table The name of the table to insert data into.
* @param array $data An associative array containing column-value pairs.
* @return integer The number of affected rows.
*/
public function insert($tableName, array $data)
{
$this->connect();
// column names are specified as array keys
$cols = array();
$placeholders = array();
foreach ($data as $columnName => $value) {
$cols[] = $columnName;
$placeholders[] = '?';
}
$query = 'INSERT INTO ' . $tableName
. ' (' . implode(', ', $cols) . ')'
. ' VALUES (' . implode(', ', $placeholders) . ')';
return $this->executeUpdate($query, array_values($data));
}
/**
* Sets the given charset on the current connection.
*
* @param string $charset The charset to set.
*/
public function setCharset($charset)
{
$this->executeUpdate($this->_platform->getSetCharsetSQL($charset));
}
/**
* Quote a string so it can be safely used as a table or column name, even if
* it is a reserved name.
*
* Delimiting style depends on the underlying database platform that is being used.
*
* NOTE: Just because you CAN use quoted identifiers does not mean
* you SHOULD use them. In general, they end up causing way more
* problems than they solve.
*
* @param string $str The name to be quoted.
* @return string The quoted name.
*/
public function quoteIdentifier($str)
{
return $this->_platform->quoteIdentifier($str);
}
/**
* Quotes a given input parameter.
*
* @param mixed $input Parameter to be quoted.
* @param string $type Type of the parameter.
* @return string The quoted parameter.
*/
public function quote($input, $type = null)
{
$this->connect();
return $this->_conn->quote($input, $type);
}
/**
* Prepares and executes an SQL query and returns the result as an associative array.
*
* @param string $sql The SQL query.
* @param array $params The query parameters.
* @return array
*/
public function fetchAll($sql, array $params = array())
{
return $this->executeQuery($sql, $params)->fetchAll(PDO::FETCH_ASSOC);
}
/**
* Prepares an SQL statement.
*
* @param string $statement The SQL statement to prepare.
* @return Doctrine\DBAL\Driver\Statement The prepared statement.
*/
public function prepare($statement)
{
$this->connect();
return new Statement($statement, $this);
}
/**
* Executes an, optionally parameterized, SQL query.
*
* If the query is parameterized, a prepared statement is used.
* If an SQLLogger is configured, the execution is logged.
*
* @param string $query The SQL query to execute.
* @param array $params The parameters to bind to the query, if any.
* @return Doctrine\DBAL\Driver\Statement The executed statement.
* @internal PERF: Directly prepares a driver statement, not a wrapper.
*/
public function executeQuery($query, array $params = array(), $types = array())
{
$this->connect();
$hasLogger = $this->_config->getSQLLogger() !== null;
if ($hasLogger) {
$this->_config->getSQLLogger()->startQuery($query, $params, $types);
}
if ($params) {
$stmt = $this->_conn->prepare($query);
if ($types) {
$this->_bindTypedValues($stmt, $params, $types);
$stmt->execute();
} else {
$stmt->execute($params);
}
} else {
$stmt = $this->_conn->query($query);
}
if ($hasLogger) {
$this->_config->getSQLLogger()->stopQuery();
}
return $stmt;
}
/**
* Executes an, optionally parameterized, SQL query and returns the result,
* applying a given projection/transformation function on each row of the result.
*
* @param string $query The SQL query to execute.
* @param array $params The parameters, if any.
* @param Closure $mapper The transformation function that is applied on each row.
* The function receives a single paramater, an array, that
* represents a row of the result set.
* @return mixed The projected result of the query.
*/
public function project($query, array $params, Closure $function)
{
$result = array();
$stmt = $this->executeQuery($query, $params ?: array());
while ($row = $stmt->fetch()) {
$result[] = $function($row);
}
$stmt->closeCursor();
return $result;
}
/**
* Executes an SQL statement, returning a result set as a Statement object.
*
* @param string $statement
* @param integer $fetchType
* @return Doctrine\DBAL\Driver\Statement
*/
public function query()
{
$this->connect();
return call_user_func_array(array($this->_conn, 'query'), func_get_args());
}
/**
* Executes an SQL INSERT/UPDATE/DELETE query with the given parameters
* and returns the number of affected rows.
*
* This method supports PDO binding types as well as DBAL mapping types.
*
* @param string $query The SQL query.
* @param array $params The query parameters.
* @param array $types The parameter types.
* @return integer The number of affected rows.
* @internal PERF: Directly prepares a driver statement, not a wrapper.
*/
public function executeUpdate($query, array $params = array(), array $types = array())
{
$this->connect();
$hasLogger = $this->_config->getSQLLogger() !== null;
if ($hasLogger) {
$this->_config->getSQLLogger()->startQuery($query, $params, $types);
}
if ($params) {
$stmt = $this->_conn->prepare($query);
if ($types) {
$this->_bindTypedValues($stmt, $params, $types);
$stmt->execute();
} else {
$stmt->execute($params);
}
$result = $stmt->rowCount();
} else {
$result = $this->_conn->exec($query);
}
if ($hasLogger) {
$this->_config->getSQLLogger()->stopQuery();
}
return $result;
}
/**
* Execute an SQL statement and return the number of affected rows.
*
* @param string $statement
* @return integer The number of affected rows.
*/
public function exec($statement)
{
$this->connect();
return $this->_conn->exec($statement);
}
/**
* Returns the current transaction nesting level.
*
* @return integer The nesting level. A value of 0 means there's no active transaction.
*/
public function getTransactionNestingLevel()
{
return $this->_transactionNestingLevel;
}
/**
* Fetch the SQLSTATE associated with the last database operation.
*
* @return integer The last error code.
*/
public function errorCode()
{
$this->connect();
return $this->_conn->errorCode();
}
/**
* Fetch extended error information associated with the last database operation.
*
* @return array The last error information.
*/
public function errorInfo()
{
$this->connect();
return $this->_conn->errorInfo();
}
/**
* Returns the ID of the last inserted row, or the last value from a sequence object,
* depending on the underlying driver.
*
* Note: This method may not return a meaningful or consistent result across different drivers,
* because the underlying database may not even support the notion of AUTO_INCREMENT/IDENTITY
* columns or sequences.
*
* @param string $seqName Name of the sequence object from which the ID should be returned.
* @return string A string representation of the last inserted ID.
*/
public function lastInsertId($seqName = null)
{
$this->connect();
return $this->_conn->lastInsertId($seqName);
}
/**
* Executes a function in a transaction.
*
* The function gets passed this Connection instance as an (optional) parameter.
*
* If an exception occurs during execution of the function or transaction commit,
* the transaction is rolled back and the exception re-thrown.
*
* @param Closure $func The function to execute transactionally.
*/
public function transactional(Closure $func)
{
$this->beginTransaction();
try {
$func($this);
$this->commit();
} catch (Exception $e) {
$this->rollback();
throw $e;
}
}
/**
* Set if nested transactions should use savepoints
*
* @param boolean
* @return void
*/
public function setNestTransactionsWithSavepoints($nestTransactionsWithSavepoints)
{
if ($this->_transactionNestingLevel > 0) {
throw ConnectionException::mayNotAlterNestedTransactionWithSavepointsInTransaction();
}
if (!$this->_platform->supportsSavepoints()) {
throw ConnectionException::savepointsNotSupported();
}
$this->_nestTransactionsWithSavepoints = $nestTransactionsWithSavepoints;
}
/**
* Get if nested transactions should use savepoints
*
* @return boolean
*/
public function getNestTransactionsWithSavepoints()
{
return $this->_nestTransactionsWithSavepoints;
}
/**
* Returns the savepoint name to use for nested transactions are false if they are not supported
* "savepointFormat" parameter is not set
*
* @return mixed a string with the savepoint name or false
*/
protected function _getNestedTransactionSavePointName()
{
return 'DOCTRINE2_SAVEPOINT_'.$this->_transactionNestingLevel;
}
/**
* Starts a transaction by suspending auto-commit mode.
*
* @return void
*/
public function beginTransaction()
{
$this->connect();
++$this->_transactionNestingLevel;
if ($this->_transactionNestingLevel == 1) {
$this->_conn->beginTransaction();
} else if ($this->_nestTransactionsWithSavepoints) {
$this->createSavepoint($this->_getNestedTransactionSavePointName());
}
}
/**
* Commits the current transaction.
*
* @return void
* @throws ConnectionException If the commit failed due to no active transaction or
* because the transaction was marked for rollback only.
*/
public function commit()
{
if ($this->_transactionNestingLevel == 0) {
throw ConnectionException::noActiveTransaction();
}
if ($this->_isRollbackOnly) {
throw ConnectionException::commitFailedRollbackOnly();
}
$this->connect();
if ($this->_transactionNestingLevel == 1) {
$this->_conn->commit();
} else if ($this->_nestTransactionsWithSavepoints) {
$this->releaseSavepoint($this->_getNestedTransactionSavePointName());
}
--$this->_transactionNestingLevel;
}
/**
* Cancel any database changes done during the current transaction.
*
* this method can be listened with onPreTransactionRollback and onTransactionRollback
* eventlistener methods
*
* @throws ConnectionException If the rollback operation failed.
*/
public function rollback()
{
if ($this->_transactionNestingLevel == 0) {
throw ConnectionException::noActiveTransaction();
}
$this->connect();
if ($this->_transactionNestingLevel == 1) {
$this->_transactionNestingLevel = 0;
$this->_conn->rollback();
$this->_isRollbackOnly = false;
} else if ($this->_nestTransactionsWithSavepoints) {
$this->rollbackSavepoint($this->_getNestedTransactionSavePointName());
--$this->_transactionNestingLevel;
} else {
$this->_isRollbackOnly = true;
--$this->_transactionNestingLevel;
}
}
/**
* createSavepoint
* creates a new savepoint
*
* @param string $savepoint name of a savepoint to set
* @return void
*/
public function createSavepoint($savepoint)
{
if (!$this->_platform->supportsSavepoints()) {
throw ConnectionException::savepointsNotSupported();
}
$this->_conn->exec($this->_platform->createSavePoint($savepoint));
}
/**
* releaseSavePoint
* releases given savepoint
*
* @param string $savepoint name of a savepoint to release
* @return void
*/
public function releaseSavepoint($savepoint)
{
if (!$this->_platform->supportsSavepoints()) {
throw ConnectionException::savepointsNotSupported();
}
if ($this->_platform->supportsReleaseSavepoints()) {
$this->_conn->exec($this->_platform->releaseSavePoint($savepoint));
}
}
/**
* rollbackSavePoint
* releases given savepoint
*
* @param string $savepoint name of a savepoint to rollback to
* @return void
*/
public function rollbackSavepoint($savepoint)
{
if (!$this->_platform->supportsSavepoints()) {
throw ConnectionException::savepointsNotSupported();
}
$this->_conn->exec($this->_platform->rollbackSavePoint($savepoint));
}
/**
* Gets the wrapped driver connection.
*
* @return Doctrine\DBAL\Driver\Connection
*/
public function getWrappedConnection()
{
$this->connect();
return $this->_conn;
}
/**
* Gets the SchemaManager that can be used to inspect or change the
* database schema through the connection.
*
* @return Doctrine\DBAL\Schema\SchemaManager
*/
public function getSchemaManager()
{
if ( ! $this->_schemaManager) {
$this->_schemaManager = $this->_driver->getSchemaManager($this);
}
return $this->_schemaManager;
}
/**
* Marks the current transaction so that the only possible
* outcome for the transaction to be rolled back.
*
* @throws ConnectionException If no transaction is active.
*/
public function setRollbackOnly()
{
if ($this->_transactionNestingLevel == 0) {
throw ConnectionException::noActiveTransaction();
}
$this->_isRollbackOnly = true;
}
/**
* Check whether the current transaction is marked for rollback only.
*
* @return boolean
* @throws ConnectionException If no transaction is active.
*/
public function isRollbackOnly()
{
if ($this->_transactionNestingLevel == 0) {
throw ConnectionException::noActiveTransaction();
}
return $this->_isRollbackOnly;
}
/**
* Converts a given value to its database representation according to the conversion
* rules of a specific DBAL mapping type.
*
* @param mixed $value The value to convert.
* @param string $type The name of the DBAL mapping type.
* @return mixed The converted value.
*/
public function convertToDatabaseValue($value, $type)
{
return Type::getType($type)->convertToDatabaseValue($value, $this->_platform);
}
/**
* Converts a given value to its PHP representation according to the conversion
* rules of a specific DBAL mapping type.
*
* @param mixed $value The value to convert.
* @param string $type The name of the DBAL mapping type.
* @return mixed The converted type.
*/
public function convertToPHPValue($value, $type)
{
return Type::getType($type)->convertToPHPValue($value, $this->_platform);
}
/**
* Binds a set of parameters, some or all of which are typed with a PDO binding type
* or DBAL mapping type, to a given statement.
*
* @param $stmt The statement to bind the values to.
* @param array $params The map/list of named/positional parameters.
* @param array $types The parameter types (PDO binding types or DBAL mapping types).
* @internal Duck-typing used on the $stmt parameter to support driver statements as well as
* raw PDOStatement instances.
*/
private function _bindTypedValues($stmt, array $params, array $types)
{
// Check whether parameters are positional or named. Mixing is not allowed, just like in PDO.
if (is_int(key($params))) {
// Positional parameters
$typeOffset = isset($types[0]) ? -1 : 0;
$bindIndex = 1;
foreach ($params as $position => $value) {
$typeIndex = $bindIndex + $typeOffset;
if (isset($types[$typeIndex])) {
$type = $types[$typeIndex];
if (is_string($type)) {
$type = Type::getType($type);
}
if ($type instanceof Type) {
$value = $type->convertToDatabaseValue($value, $this->_platform);
$bindingType = $type->getBindingType();
} else {
$bindingType = $type; // PDO::PARAM_* constants
}
$stmt->bindValue($bindIndex, $value, $bindingType);
} else {
$stmt->bindValue($bindIndex, $value);
}
++$bindIndex;
}
} else {
// Named parameters
foreach ($params as $name => $value) {
if (isset($types[$name])) {
$type = $types[$name];
if (is_string($type)) {
$type = Type::getType($type);
}
if ($type instanceof Type) {
$value = $type->convertToDatabaseValue($value, $this->_platform);
$bindingType = $type->getBindingType();
} else {
$bindingType = $type; // PDO::PARAM_* constants
}
$stmt->bindValue($name, $value, $bindingType);
} else {
$stmt->bindValue($name, $value);
}
}
}
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Logging;
/**
* A SQL logger that logs to the standard output using echo/var_dump.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class EchoSQLLogger implements SQLLogger
{
/**
* {@inheritdoc}
*/
public function startQuery($sql, array $params = null, array $types = null)
{
echo $sql . PHP_EOL;
if ($params) {
var_dump($params);
}
if ($types) {
var_dump($types);
}
}
/**
* {@inheritdoc}
*/
public function stopQuery()
{
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Logging;
/**
* Includes executed SQLs in a Debug Stack
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class DebugStack implements SQLLogger
{
/** @var array $queries Executed SQL queries. */
public $queries = array();
/** @var boolean $enabled If Debug Stack is enabled (log queries) or not. */
public $enabled = true;
public $start = null;
/**
* {@inheritdoc}
*/
public function startQuery($sql, array $params = null, array $types = null)
{
if ($this->enabled) {
$this->start = microtime(true);
$this->queries[] = array('sql' => $sql, 'params' => $params, 'types' => $types, 'executionMS' => 0);
}
}
/**
* {@inheritdoc}
*/
public function stopQuery()
{
$this->queries[(count($this->queries)-1)]['executionMS'] = microtime(true) - $this->start;
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Logging;
/**
* Interface for SQL loggers.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
interface SQLLogger
{
/**
* Logs a SQL statement somewhere.
*
* @param string $sql The SQL to be executed.
* @param array $params The SQL parameters.
* @param float $executionMS The microtime difference it took to execute this query.
* @return void
*/
public function startQuery($sql, array $params = null, array $types = null);
/**
* Mark the last started query as stopped. This can be used for timing of queries.
*
* @return void
*/
public function stopQuery();
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Tools\Console\Command;
use Symfony\Component\Console\Input\InputArgument,
Symfony\Component\Console;
/**
* Task for executing arbitrary SQL that can come from a file or directly from
* the command line.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class ImportCommand extends Console\Command\Command
{
/**
* @see Console\Command\Command
*/
protected function configure()
{
$this
->setName('dbal:import')
->setDescription('Import SQL file(s) directly to Database.')
->setDefinition(array(
new InputArgument(
'file', InputArgument::REQUIRED | InputArgument::IS_ARRAY, 'File path(s) of SQL to be executed.'
)
))
->setHelp(<<<EOT
Import SQL file(s) directly to Database.
EOT
);
}
/**
* @see Console\Command\Command
*/
protected function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output)
{
$conn = $this->getHelper('db')->getConnection();
if (($fileNames = $input->getArgument('file')) !== null) {
foreach ((array) $fileNames as $fileName) {
$fileName = realpath($fileName);
if ( ! file_exists($fileName)) {
throw new \InvalidArgumentException(
sprintf("SQL file '<info>%s</info>' does not exist.", $fileName)
);
} else if ( ! is_readable($fileName)) {
throw new \InvalidArgumentException(
sprintf("SQL file '<info>%s</info>' does not have read permissions.", $fileName)
);
}
$output->write(sprintf("Processing file '<info>%s</info>'... ", $fileName));
$sql = file_get_contents($fileName);
if ($conn instanceof \Doctrine\DBAL\Driver\PDOConnection) {
// PDO Drivers
try {
$lines = 0;
$stmt = $conn->prepare($sql);
$stmt->execute();
do {
// Required due to "MySQL has gone away!" issue
$stmt->fetch();
$stmt->closeCursor();
$lines++;
} while ($stmt->nextRowset());
$output->write(sprintf('%d statements executed!', $lines) . PHP_EOL);
} catch (\PDOException $e) {
$output->write('error!' . PHP_EOL);
throw new \RuntimeException($e->getMessage(), $e->getCode(), $e);
}
} else {
// Non-PDO Drivers (ie. OCI8 driver)
$stmt = $conn->prepare($sql);
$rs = $stmt->execute();
if ($rs) {
$printer->writeln('OK!');
} else {
$error = $stmt->errorInfo();
$output->write('error!' . PHP_EOL);
throw new \RuntimeException($error[2], $error[0]);
}
$stmt->closeCursor();
}
}
}
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Tools\Console\Command;
use Symfony\Component\Console\Input\InputArgument,
Symfony\Component\Console\Input\InputOption,
Symfony\Component\Console;
/**
* Task for executing arbitrary SQL that can come from a file or directly from
* the command line.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class RunSqlCommand extends Console\Command\Command
{
/**
* @see Console\Command\Command
*/
protected function configure()
{
$this
->setName('dbal:run-sql')
->setDescription('Executes arbitrary SQL directly from the command line.')
->setDefinition(array(
new InputArgument('sql', InputArgument::REQUIRED, 'The SQL statement to execute.'),
new InputOption('depth', null, InputOption::PARAMETER_REQUIRED, 'Dumping depth of result set.', 7)
))
->setHelp(<<<EOT
Executes arbitrary SQL directly from the command line.
EOT
);
}
/**
* @see Console\Command\Command
*/
protected function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output)
{
$conn = $this->getHelper('db')->getConnection();
if (($sql = $input->getArgument('sql')) === null) {
throw new \RuntimeException("Argument 'SQL' is required in order to execute this command correctly.");
}
$depth = $input->getOption('depth');
if ( ! is_numeric($depth)) {
throw new \LogicException("Option 'depth' must contains an integer value");
}
if (preg_match('/^select/i', $sql)) {
$resultSet = $conn->fetchAll($sql);
} else {
$resultSet = $conn->executeUpdate($sql);
}
\Doctrine\Common\Util\Debug::dump($resultSet, (int) $depth);
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Tools\Console\Helper;
use Symfony\Component\Console\Helper\Helper,
Doctrine\DBAL\Connection;
/**
* Doctrine CLI Connection Helper.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class ConnectionHelper extends Helper
{
/**
* Doctrine Database Connection
* @var Connection
*/
protected $_connection;
/**
* Constructor
*
* @param Connection $connection Doctrine Database Connection
*/
public function __construct(Connection $connection)
{
$this->_connection = $connection;
}
/**
* Retrieves Doctrine Database Connection
*
* @return Connection
*/
public function getConnection()
{
return $this->_connection;
}
/**
* @see Helper
*/
public function getName()
{
return 'connection';
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Types;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* Variable DateTime Type using date_create() instead of DateTime::createFromFormat()
*
* This type has performance implications as it runs twice as long as the regular
* {@see DateTimeType}, however in certain PostgreSQL configurations with
* TIMESTAMP(n) columns where n > 0 it is necessary to use this type.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class VarDateTimeType extends DateTimeType
{
/**
* @throws ConversionException
* @param string $value
* @param AbstractPlatform $platform
* @return DateTime
*/
public function convertToPHPValue($value, AbstractPlatform $platform)
{
if ($value === null) {
return null;
}
$val = date_create($value);
if (!$val) {
throw ConversionException::conversionFailed($value, $this->getName());
}
return $val;
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Types;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* Type that maps an SQL INT to a PHP integer.
*
* @author Roman Borschel <roman@code-factory.org>
* @since 2.0
*/
class IntegerType extends Type
{
public function getName()
{
return Type::INTEGER;
}
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getIntegerTypeDeclarationSQL($fieldDeclaration);
}
public function convertToPHPValue($value, AbstractPlatform $platform)
{
return (null === $value) ? null : (int) $value;
}
public function getBindingType()
{
return \PDO::PARAM_INT;
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Types;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* Type that maps an SQL DATE to a PHP Date object.
*
* @since 2.0
*/
class DateType extends Type
{
public function getName()
{
return Type::DATE;
}
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getDateTypeDeclarationSQL($fieldDeclaration);
}
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
return ($value !== null)
? $value->format($platform->getDateFormatString()) : null;
}
public function convertToPHPValue($value, AbstractPlatform $platform)
{
if ($value === null) {
return null;
}
$val = \DateTime::createFromFormat('!'.$platform->getDateFormatString(), $value);
if (!$val) {
throw ConversionException::conversionFailed($value, $this->getName());
}
return $val;
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Types;
use Doctrine\DBAL\Platforms\AbstractPlatform,
Doctrine\DBAL\DBALException;
/**
* The base class for so-called Doctrine mapping types.
*
* A Type object is obtained by calling the static {@link getType()} method.
*
* @author Roman Borschel <roman@code-factory.org>
* @since 2.0
*/
abstract class Type
{
const TARRAY = 'array';
const BIGINT = 'bigint';
const BOOLEAN = 'boolean';
const DATETIME = 'datetime';
const DATETIMETZ = 'datetimetz';
const DATE = 'date';
const TIME = 'time';
const DECIMAL = 'decimal';
const INTEGER = 'integer';
const OBJECT = 'object';
const SMALLINT = 'smallint';
const STRING = 'string';
const TEXT = 'text';
const FLOAT = 'float';
/** Map of already instantiated type objects. One instance per type (flyweight). */
private static $_typeObjects = array();
/** The map of supported doctrine mapping types. */
private static $_typesMap = array(
self::TARRAY => 'Doctrine\DBAL\Types\ArrayType',
self::OBJECT => 'Doctrine\DBAL\Types\ObjectType',
self::BOOLEAN => 'Doctrine\DBAL\Types\BooleanType',
self::INTEGER => 'Doctrine\DBAL\Types\IntegerType',
self::SMALLINT => 'Doctrine\DBAL\Types\SmallIntType',
self::BIGINT => 'Doctrine\DBAL\Types\BigIntType',
self::STRING => 'Doctrine\DBAL\Types\StringType',
self::TEXT => 'Doctrine\DBAL\Types\TextType',
self::DATETIME => 'Doctrine\DBAL\Types\DateTimeType',
self::DATETIMETZ => 'Doctrine\DBAL\Types\DateTimeTzType',
self::DATE => 'Doctrine\DBAL\Types\DateType',
self::TIME => 'Doctrine\DBAL\Types\TimeType',
self::DECIMAL => 'Doctrine\DBAL\Types\DecimalType',
self::FLOAT => 'Doctrine\DBAL\Types\FloatType',
);
/* Prevent instantiation and force use of the factory method. */
final private function __construct() {}
/**
* Converts a value from its PHP representation to its database representation
* of this type.
*
* @param mixed $value The value to convert.
* @param AbstractPlatform $platform The currently used database platform.
* @return mixed The database representation of the value.
*/
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
return $value;
}
/**
* Converts a value from its database representation to its PHP representation
* of this type.
*
* @param mixed $value The value to convert.
* @param AbstractPlatform $platform The currently used database platform.
* @return mixed The PHP representation of the value.
*/
public function convertToPHPValue($value, AbstractPlatform $platform)
{
return $value;
}
/**
* Gets the default length of this type.
*
* @todo Needed?
*/
public function getDefaultLength(AbstractPlatform $platform)
{
return null;
}
/**
* Gets the SQL declaration snippet for a field of this type.
*
* @param array $fieldDeclaration The field declaration.
* @param AbstractPlatform $platform The currently used database platform.
*/
abstract public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform);
/**
* Gets the name of this type.
*
* @return string
* @todo Needed?
*/
abstract public function getName();
/**
* Factory method to create type instances.
* Type instances are implemented as flyweights.
*
* @static
* @throws DBALException
* @param string $name The name of the type (as returned by getName()).
* @return Doctrine\DBAL\Types\Type
*/
public static function getType($name)
{
if ( ! isset(self::$_typeObjects[$name])) {
if ( ! isset(self::$_typesMap[$name])) {
throw DBALException::unknownColumnType($name);
}
self::$_typeObjects[$name] = new self::$_typesMap[$name]();
}
return self::$_typeObjects[$name];
}
/**
* Adds a custom type to the type map.
*
* @static
* @param string $name Name of the type. This should correspond to what getName() returns.
* @param string $className The class name of the custom type.
* @throws DBALException
*/
public static function addType($name, $className)
{
if (isset(self::$_typesMap[$name])) {
throw DBALException::typeExists($name);
}
self::$_typesMap[$name] = $className;
}
/**
* Checks if exists support for a type.
*
* @static
* @param string $name Name of the type
* @return boolean TRUE if type is supported; FALSE otherwise
*/
public static function hasType($name)
{
return isset(self::$_typesMap[$name]);
}
/**
* Overrides an already defined type to use a different implementation.
*
* @static
* @param string $name
* @param string $className
* @throws DBALException
*/
public static function overrideType($name, $className)
{
if ( ! isset(self::$_typesMap[$name])) {
throw DBALException::typeNotFound($name);
}
self::$_typesMap[$name] = $className;
}
/**
* Gets the (preferred) binding type for values of this type that
* can be used when binding parameters to prepared statements.
*
* This method should return one of the PDO::PARAM_* constants, that is, one of:
*
* PDO::PARAM_BOOL
* PDO::PARAM_NULL
* PDO::PARAM_INT
* PDO::PARAM_STR
* PDO::PARAM_LOB
*
* @return integer
*/
public function getBindingType()
{
return \PDO::PARAM_STR;
}
/**
* Get the types array map which holds all registered types and the corresponding
* type class
*
* @return array $typesMap
*/
public static function getTypesMap()
{
return self::$_typesMap;
}
public function __toString()
{
$e = explode('\\', get_class($this));
return str_replace('Type', '', end($e));
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Types;
use Doctrine\DBAL\Platforms\AbstractPlatform;
class FloatType extends Type
{
public function getName()
{
return Type::FLOAT;
}
/**
* @param array $fieldDeclaration
* @param AbstractPlatform $platform
* @return string
*/
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getFloatDeclarationSQL($fieldDeclaration);
}
/**
* Converts a value from its database representation to its PHP representation
* of this type.
*
* @param mixed $value The value to convert.
* @param AbstractPlatform $platform The currently used database platform.
* @return mixed The PHP representation of the value.
*/
public function convertToPHPValue($value, AbstractPlatform $platform)
{
return (null === $value) ? null : (double) $value;
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Types;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* Type that maps a database SMALLINT to a PHP integer.
*
* @author robo
*/
class SmallIntType extends Type
{
public function getName()
{
return Type::SMALLINT;
}
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getSmallIntTypeDeclarationSQL($fieldDeclaration);
}
public function convertToPHPValue($value, AbstractPlatform $platform)
{
return (null === $value) ? null : (int) $value;
}
public function getBindingType()
{
return \PDO::PARAM_INT;
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Types;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* Type that maps a database BIGINT to a PHP string.
*
* @author robo
* @since 2.0
*/
class BigIntType extends Type
{
public function getName()
{
return Type::BIGINT;
}
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getBigIntTypeDeclarationSQL($fieldDeclaration);
}
public function getBindingType()
{
return \PDO::PARAM_INT;
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Types;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* Type that maps an SQL VARCHAR to a PHP string.
*
* @since 2.0
*/
class StringType extends Type
{
/** @override */
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getVarcharTypeDeclarationSQL($fieldDeclaration);
}
/** @override */
public function getDefaultLength(AbstractPlatform $platform)
{
return $platform->getVarcharDefaultLength();
}
/** @override */
public function getName()
{
return Type::STRING;
}
}<?php
namespace Doctrine\DBAL\Types;
/**
* Type that maps a PHP object to a clob SQL type.
*
* @since 2.0
*/
class ObjectType extends Type
{
public function getSQLDeclaration(array $fieldDeclaration, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{
return $platform->getClobTypeDeclarationSQL($fieldDeclaration);
}
public function convertToDatabaseValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{
return serialize($value);
}
public function convertToPHPValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{
if ($value === null) {
return null;
}
$value = (is_resource($value)) ? stream_get_contents($value) : $value;
$val = unserialize($value);
if ($val === false) {
throw ConversionException::conversionFailed($value, $this->getName());
}
return $val;
}
public function getName()
{
return Type::OBJECT;
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Types;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* DateTime type saving additional timezone information.
*
* Caution: Databases are not necessarily experts at storing timezone related
* data of dates. First, of all the supported vendors only PostgreSQL and Oracle
* support storing Timezone data. But those two don't save the actual timezone
* attached to a DateTime instance (for example "Europe/Berlin" or "America/Montreal")
* but the current offset of them related to UTC. That means depending on daylight saving times
* or not you may get different offsets.
*
* This datatype makes only sense to use, if your application works with an offset, not
* with an actual timezone that uses transitions. Otherwise your DateTime instance
* attached with a timezone such as Europe/Berlin gets saved into the database with
* the offset and re-created from persistence with only the offset, not the original timezone
* attached.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 1.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class DateTimeTzType extends Type
{
public function getName()
{
return Type::DATETIMETZ;
}
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getDateTimeTzTypeDeclarationSQL($fieldDeclaration);
}
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
return ($value !== null)
? $value->format($platform->getDateTimeTzFormatString()) : null;
}
public function convertToPHPValue($value, AbstractPlatform $platform)
{
if ($value === null) {
return null;
}
$val = \DateTime::createFromFormat($platform->getDateTimeTzFormatString(), $value);
if (!$val) {
throw ConversionException::conversionFailed($value, $this->getName());
}
return $val;
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
/**
* Conversion Exception is thrown when the database to PHP conversion fails
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
namespace Doctrine\DBAL\Types;
class ConversionException extends \Doctrine\DBAL\DBALException
{
/**
* Thrown when a Database to Doctrine Type Conversion fails.
*
* @param string $value
* @param string $toType
* @return ConversionException
*/
static public function conversionFailed($value, $toType)
{
$value = (strlen($value) > 32) ? substr($value, 0, 20) . "..." : $value;
return new self('Could not convert database value "' . $value . '" to Doctrine Type ' . $toType);
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Types;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* Type that maps an SQL DATETIME/TIMESTAMP to a PHP DateTime object.
*
* @since 2.0
*/
class DateTimeType extends Type
{
public function getName()
{
return Type::DATETIME;
}
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getDateTimeTypeDeclarationSQL($fieldDeclaration);
}
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
return ($value !== null)
? $value->format($platform->getDateTimeFormatString()) : null;
}
public function convertToPHPValue($value, AbstractPlatform $platform)
{
if ($value === null) {
return null;
}
$val = \DateTime::createFromFormat($platform->getDateTimeFormatString(), $value);
if (!$val) {
throw ConversionException::conversionFailed($value, $this->getName());
}
return $val;
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Types;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* Type that maps an SQL DECIMAL to a PHP double.
*
* @since 2.0
*/
class DecimalType extends Type
{
public function getName()
{
return Type::DECIMAL;
}
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getDecimalTypeDeclarationSQL($fieldDeclaration);
}
public function convertToPHPValue($value, AbstractPlatform $platform)
{
return (null === $value) ? null : (double) $value;
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Types;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* Type that maps an SQL CLOB to a PHP string.
*
* @since 2.0
*/
class TextType extends Type
{
/** @override */
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getClobTypeDeclarationSQL($fieldDeclaration);
}
/**
* Converts a value from its database representation to its PHP representation
* of this type.
*
* @param mixed $value The value to convert.
* @param AbstractPlatform $platform The currently used database platform.
* @return mixed The PHP representation of the value.
*/
public function convertToPHPValue($value, AbstractPlatform $platform)
{
return (is_resource($value)) ? stream_get_contents($value) : $value;
}
public function getName()
{
return Type::TEXT;
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Types;
/**
* Type that maps a PHP array to a clob SQL type.
*
* @since 2.0
*/
class ArrayType extends Type
{
public function getSQLDeclaration(array $fieldDeclaration, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{
return $platform->getClobTypeDeclarationSQL($fieldDeclaration);
}
public function convertToDatabaseValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{
return serialize($value);
}
public function convertToPHPValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{
if ($value === null) {
return null;
}
$value = (is_resource($value)) ? stream_get_contents($value) : $value;
$val = unserialize($value);
if ($val === false) {
throw ConversionException::conversionFailed($value, $this->getName());
}
return $val;
}
public function getName()
{
return Type::TARRAY;
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Types;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* Type that maps an SQL boolean to a PHP boolean.
*
* @since 2.0
*/
class BooleanType extends Type
{
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getBooleanTypeDeclarationSQL($fieldDeclaration);
}
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
return $platform->convertBooleans($value);
}
public function convertToPHPValue($value, AbstractPlatform $platform)
{
return (null === $value) ? null : (bool) $value;
}
public function getName()
{
return Type::BOOLEAN;
}
public function getBindingType()
{
return \PDO::PARAM_BOOL;
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Types;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* Type that maps an SQL TIME to a PHP DateTime object.
*
* @since 2.0
*/
class TimeType extends Type
{
public function getName()
{
return Type::TIME;
}
/**
* {@inheritdoc}
*/
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getTimeTypeDeclarationSQL($fieldDeclaration);
}
/**
* {@inheritdoc}
*/
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
return ($value !== null)
? $value->format($platform->getTimeFormatString()) : null;
}
/**
* {@inheritdoc}
*/
public function convertToPHPValue($value, AbstractPlatform $platform)
{
if ($value === null) {
return null;
}
$val = \DateTime::createFromFormat($platform->getTimeFormatString(), $value);
if (!$val) {
throw ConversionException::conversionFailed($value, $this->getName());
}
return $val;
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Event;
use Doctrine\Common\EventArgs,
Doctrine\DBAL\Connection;
/**
* Event Arguments used when a Driver connection is established inside Doctrine\DBAL\Connection.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 1.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class ConnectionEventArgs extends EventArgs
{
/**
* @var Connection
*/
private $_connection = null;
public function __construct(Connection $connection)
{
$this->_connection = $connection;
}
/**
* @return Doctrine\DBAL\Connection
*/
public function getConnection()
{
return $this->_connection;
}
/**
* @return Doctrine\DBAL\Driver
*/
public function getDriver()
{
return $this->_connection->getDriver();
}
/**
* @return Doctrine\DBAL\Platforms\AbstractPlatform
*/
public function getDatabasePlatform()
{
return $this->_connection->getDatabasePlatform();
}
/**
* @return Doctrine\DBAL\Schema\AbstractSchemaManager
*/
public function getSchemaManager()
{
return $this->_connection->getSchemaManager();
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Event\Listeners;
use Doctrine\DBAL\Event\ConnectionEventArgs;
use Doctrine\DBAL\Events;
use Doctrine\Common\EventSubscriber;
/**
* MySQL Session Init Event Subscriber which allows to set the Client Encoding of the Connection
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 1.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class MysqlSessionInit implements EventSubscriber
{
/**
* @var string
*/
private $_charset;
/**
* @var string
*/
private $_collation;
/**
* Configure Charset and Collation options of MySQL Client for each Connection
*
* @param string $charset
* @param string $collation
*/
public function __construct($charset = 'utf8', $collation = false)
{
$this->_charset = $charset;
$this->_collation = $collation;
}
/**
* @param ConnectionEventArgs $args
* @return void
*/
public function postConnect(ConnectionEventArgs $args)
{
$collation = ($this->_collation) ? " COLLATE ".$this->_collation : "";
$args->getConnection()->executeUpdate("SET NAMES ".$this->_charset . $collation);
}
public function getSubscribedEvents()
{
return array(Events::postConnect);
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Event\Listeners;
use Doctrine\DBAL\Event\ConnectionEventArgs;
use Doctrine\DBAL\Events;
use Doctrine\Common\EventSubscriber;
/**
* Should be used when Oracle Server default enviroment does not match the Doctrine requirements.
*
* The following enviroment variables are required for the Doctrine default date format:
*
* NLS_TIME_FORMAT="HH24:MI:SS"
* NLS_DATE_FORMAT="YYYY-MM-DD"
* NLS_TIMESTAMP_FORMAT="YYYY-MM-DD HH24:MI:SS"
* NLS_TIMESTAMP_TZ_FORMAT="YYYY-MM-DD HH24:MI:SS TZH:TZM"
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 1.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class OracleSessionInit implements EventSubscriber
{
protected $_defaultSessionVars = array(
'NLS_TIME_FORMAT' => "HH24:MI:SS",
'NLS_DATE_FORMAT' => "YYYY-MM-DD HH24:MI:SS",
'NLS_TIMESTAMP_FORMAT' => "YYYY-MM-DD HH24:MI:SS",
'NLS_TIMESTAMP_TZ_FORMAT' => "YYYY-MM-DD HH24:MI:SS TZH:TZM",
);
/**
* @param array $oracleSessionVars
*/
public function __construct(array $oracleSessionVars = array())
{
$this->_defaultSessionVars = array_merge($this->_defaultSessionVars, $oracleSessionVars);
}
/**
* @param ConnectionEventArgs $args
* @return void
*/
public function postConnect(ConnectionEventArgs $args)
{
if (count($this->_defaultSessionVars)) {
array_change_key_case($this->_defaultSessionVars, \CASE_UPPER);
$vars = array();
foreach ($this->_defaultSessionVars AS $option => $value) {
$vars[] = $option." = '".$value."'";
}
$sql = "ALTER SESSION SET ".implode(" ", $vars);
$args->getConnection()->executeUpdate($sql);
}
}
public function getSubscribedEvents()
{
return array(Events::postConnect);
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common;
/**
* EventArgs is the base class for classes containing event data.
*
* This class contains no event data. It is used by events that do not pass state
* information to an event handler when an event is raised. The single empty EventArgs
* instance can be obtained through {@link getEmptyInstance}.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class EventArgs
{
/**
* @var EventArgs Single instance of EventArgs
* @static
*/
private static $_emptyEventArgsInstance;
/**
* Gets the single, empty and immutable EventArgs instance.
*
* This instance will be used when events are dispatched without any parameter,
* like this: EventManager::dispatchEvent('eventname');
*
* The benefit from this is that only one empty instance is instantiated and shared
* (otherwise there would be instances for every dispatched in the abovementioned form)
*
* @see EventManager::dispatchEvent
* @link http://msdn.microsoft.com/en-us/library/system.eventargs.aspx
* @static
* @return EventArgs
*/
public static function getEmptyInstance()
{
if ( ! self::$_emptyEventArgsInstance) {
self::$_emptyEventArgsInstance = new EventArgs;
}
return self::$_emptyEventArgsInstance;
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common;
/**
* Base exception class for package Doctrine\Common
* @author heinrich
*
*/
class CommonException extends \Exception {
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Annotations;
use Closure,
ReflectionClass,
ReflectionMethod,
ReflectionProperty,
Doctrine\Common\Cache\Cache;
/**
* A reader for docblock annotations.
*
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class AnnotationReader
{
/**
* Cache salt
*
* @var string
* @static
*/
private static $CACHE_SALT = '@<Annot>';
/**
* Annotations Parser
*
* @var Doctrine\Common\Annotations\Parser
*/
private $parser;
/**
* Cache mechanism to store processed Annotations
*
* @var Doctrine\Common\Cache\Cache
*/
private $cache;
/**
* Constructor. Initializes a new AnnotationReader that uses the given Cache provider.
*
* @param Cache $cache The cache provider to use. If none is provided, ArrayCache is used.
* @param Parser $parser The parser to use. If none is provided, the default parser is used.
*/
public function __construct(Cache $cache = null, Parser $parser = null)
{
$this->parser = $parser ?: new Parser;
$this->cache = $cache ?: new \Doctrine\Common\Cache\ArrayCache;
}
/**
* Sets the default namespace that the AnnotationReader should assume for annotations
* with not fully qualified names.
*
* @param string $defaultNamespace
*/
public function setDefaultAnnotationNamespace($defaultNamespace)
{
$this->parser->setDefaultAnnotationNamespace($defaultNamespace);
}
/**
* Sets the custom function to use for creating new annotations on the
* underlying parser.
*
* The function is supplied two arguments. The first argument is the name
* of the annotation and the second argument an array of values for this
* annotation. The function is assumed to return an object or NULL.
* Whenever the function returns NULL for an annotation, the implementation falls
* back to the default annotation creation process of the underlying parser.
*
* @param Closure $func
*/
public function setAnnotationCreationFunction(Closure $func)
{
$this->parser->setAnnotationCreationFunction($func);
}
/**
* Sets an alias for an annotation namespace.
*
* @param $namespace
* @param $alias
*/
public function setAnnotationNamespaceAlias($namespace, $alias)
{
$this->parser->setAnnotationNamespaceAlias($namespace, $alias);
}
/**
* Sets a flag whether to try to autoload annotation classes, as well as to distinguish
* between what is an annotation and what not by triggering autoloading.
*
* NOTE: Autoloading of annotation classes is inefficient and requires silently failing
* autoloaders. In particular, setting this option to TRUE renders this AnnotationReader
* incompatible with a {@link ClassLoader}.
* @param boolean $bool Boolean flag.
*/
public function setAutoloadAnnotations($bool)
{
$this->parser->setAutoloadAnnotations($bool);
}
/**
* Gets a flag whether to try to autoload annotation classes.
*
* @see setAutoloadAnnotations
* @return boolean
*/
public function getAutoloadAnnotations()
{
return $this->parser->getAutoloadAnnotations();
}
/**
* Gets the annotations applied to a class.
*
* @param string|ReflectionClass $class The name or ReflectionClass of the class from which
* the class annotations should be read.
* @return array An array of Annotations.
*/
public function getClassAnnotations(ReflectionClass $class)
{
$cacheKey = $class->getName() . self::$CACHE_SALT;
// Attempt to grab data from cache
if (($data = $this->cache->fetch($cacheKey)) !== false) {
return $data;
}
$annotations = $this->parser->parse($class->getDocComment(), 'class ' . $class->getName());
$this->cache->save($cacheKey, $annotations, null);
return $annotations;
}
/**
* Gets a class annotation.
*
* @param $class
* @param string $annotation The name of the annotation.
* @return The Annotation or NULL, if the requested annotation does not exist.
*/
public function getClassAnnotation(ReflectionClass $class, $annotation)
{
$annotations = $this->getClassAnnotations($class);
return isset($annotations[$annotation]) ? $annotations[$annotation] : null;
}
/**
* Gets the annotations applied to a property.
*
* @param string|ReflectionClass $class The name or ReflectionClass of the class that owns the property.
* @param string|ReflectionProperty $property The name or ReflectionProperty of the property
* from which the annotations should be read.
* @return array An array of Annotations.
*/
public function getPropertyAnnotations(ReflectionProperty $property)
{
$cacheKey = $property->getDeclaringClass()->getName() . '$' . $property->getName() . self::$CACHE_SALT;
// Attempt to grab data from cache
if (($data = $this->cache->fetch($cacheKey)) !== false) {
return $data;
}
$context = 'property ' . $property->getDeclaringClass()->getName() . "::\$" . $property->getName();
$annotations = $this->parser->parse($property->getDocComment(), $context);
$this->cache->save($cacheKey, $annotations, null);
return $annotations;
}
/**
* Gets a property annotation.
*
* @param ReflectionProperty $property
* @param string $annotation The name of the annotation.
* @return The Annotation or NULL, if the requested annotation does not exist.
*/
public function getPropertyAnnotation(ReflectionProperty $property, $annotation)
{
$annotations = $this->getPropertyAnnotations($property);
return isset($annotations[$annotation]) ? $annotations[$annotation] : null;
}
/**
* Gets the annotations applied to a method.
*
* @param string|ReflectionClass $class The name or ReflectionClass of the class that owns the method.
* @param string|ReflectionMethod $property The name or ReflectionMethod of the method from which
* the annotations should be read.
* @return array An array of Annotations.
*/
public function getMethodAnnotations(ReflectionMethod $method)
{
$cacheKey = $method->getDeclaringClass()->getName() . '#' . $method->getName() . self::$CACHE_SALT;
// Attempt to grab data from cache
if (($data = $this->cache->fetch($cacheKey)) !== false) {
return $data;
}
$context = 'method ' . $method->getDeclaringClass()->getName() . '::' . $method->getName() . '()';
$annotations = $this->parser->parse($method->getDocComment(), $context);
$this->cache->save($cacheKey, $annotations, null);
return $annotations;
}
/**
* Gets a method annotation.
*
* @param ReflectionMethod $method
* @param string $annotation The name of the annotation.
* @return The Annotation or NULL, if the requested annotation does not exist.
*/
public function getMethodAnnotation(ReflectionMethod $method, $annotation)
{
$annotations = $this->getMethodAnnotations($method);
return isset($annotations[$annotation]) ? $annotations[$annotation] : null;
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Annotations;
/**
* Description of AnnotationException
*
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class AnnotationException extends \Exception
{
/**
* Creates a new AnnotationException describing a Syntax error.
*
* @param string $message Exception message
* @return AnnotationException
*/
public static function syntaxError($message)
{
return new self('[Syntax Error] ' . $message);
}
/**
* Creates a new AnnotationException describing a Semantical error.
*
* @param string $message Exception message
* @return AnnotationException
*/
public static function semanticalError($message)
{
return new self('[Semantical Error] ' . $message);
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Annotations;
use Closure, Doctrine\Common\ClassLoader;
/**
* A simple parser for docblock annotations.
*
* This Parser can be subclassed to customize certain aspects of the annotation
* parsing and/or creation process. Note though that currently no special care
* is taken to maintain full backwards compatibility for subclasses. Implementation
* details of the default Parser can change without explicit notice.
*
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class Parser
{
/**
* Some common tags that are stripped prior to parsing in order to reduce parsing overhead.
*
* @var array
*/
private static $strippedTags = array(
"{@internal", "{@inheritdoc", "{@link"
);
/**
* The lexer.
*
* @var Doctrine\Common\Annotations\Lexer
*/
private $lexer;
/**
* Flag to control if the current annotation is nested or not.
*
* @var boolean
*/
protected $isNestedAnnotation = false;
/**
* Default namespace for annotations.
*
* @var string
*/
private $defaultAnnotationNamespace = '';
/**
* Hashmap to store namespace aliases.
*
* @var array
*/
private $namespaceAliases = array();
/**
* @var string
*/
private $context = '';
/**
* @var boolean Whether to try to autoload annotations that are not yet defined.
*/
private $autoloadAnnotations = false;
/**
* @var Closure The custom function used to create new annotations, if any.
*/
private $annotationCreationFunction;
/**
* Constructs a new AnnotationParser.
*/
public function __construct(Lexer $lexer = null)
{
$this->lexer = $lexer ?: new Lexer;
}
/**
* Gets the lexer used by this parser.
*
* @return Lexer The lexer.
*/
public function getLexer()
{
return $this->lexer;
}
/**
* Sets a flag whether to try to autoload annotation classes, as well as to distinguish
* between what is an annotation and what not by triggering autoloading.
*
* NOTE: Autoloading of annotation classes is inefficient and requires silently failing
* autoloaders. In particular, setting this option to TRUE renders the Parser
* incompatible with a {@link ClassLoader}.
* @param boolean $bool Boolean flag.
*/
public function setAutoloadAnnotations($bool)
{
$this->autoloadAnnotations = $bool;
}
/**
* Sets the custom function to use for creating new annotations.
*
* The function is supplied two arguments. The first argument is the name
* of the annotation and the second argument an array of values for this
* annotation. The function is assumed to return an object or NULL.
* Whenever the function returns NULL for an annotation, the parser falls
* back to the default annotation creation process.
*
* Whenever the function returns NULL for an annotation, the implementation falls
* back to the default annotation creation process.
*
* @param Closure $func
*/
public function setAnnotationCreationFunction(Closure $func)
{
$this->annotationCreationFunction = $func;
}
/**
* Gets a flag whether to try to autoload annotation classes.
*
* @see setAutoloadAnnotations
* @return boolean
*/
public function getAutoloadAnnotations()
{
return $this->autoloadAnnotations;
}
/**
* Sets the default namespace that is assumed for an annotation that does not
* define a namespace prefix.
*
* @param string $defaultNamespace
*/
public function setDefaultAnnotationNamespace($defaultNamespace)
{
$this->defaultAnnotationNamespace = $defaultNamespace;
}
/**
* Sets an alias for an annotation namespace.
*
* @param string $namespace
* @param string $alias
*/
public function setAnnotationNamespaceAlias($namespace, $alias)
{
$this->namespaceAliases[$alias] = $namespace;
}
/**
* Gets the namespace alias mappings used by this parser.
*
* @return array The namespace alias mappings.
*/
public function getNamespaceAliases()
{
return $this->namespaceAliases;
}
/**
* Parses the given docblock string for annotations.
*
* @param string $docBlockString The docblock string to parse.
* @param string $context The parsing context.
* @return array Array of annotations. If no annotations are found, an empty array is returned.
*/
public function parse($docBlockString, $context='')
{
$this->context = $context;
// Strip out some known inline tags.
$input = str_replace(self::$strippedTags, '', $docBlockString);
// Cut of the beginning of the input until the first '@'.
$input = substr($input, strpos($input, '@'));
$this->lexer->reset();
$this->lexer->setInput(trim($input, '* /'));
$this->lexer->moveNext();
if ($this->lexer->isNextToken(Lexer::T_AT)) {
return $this->Annotations();
}
return array();
}
/**
* Attempts to match the given token with the current lookahead token.
* If they match, updates the lookahead token; otherwise raises a syntax error.
*
* @param int Token type.
* @return bool True if tokens match; false otherwise.
*/
public function match($token)
{
if ( ! ($this->lexer->lookahead['type'] === $token)) {
$this->syntaxError($this->lexer->getLiteral($token));
}
$this->lexer->moveNext();
}
/**
* Generates a new syntax error.
*
* @param string $expected Expected string.
* @param array $token Optional token.
* @throws AnnotationException
*/
private function syntaxError($expected, $token = null)
{
if ($token === null) {
$token = $this->lexer->lookahead;
}
$message = "Expected {$expected}, got ";
if ($this->lexer->lookahead === null) {
$message .= 'end of string';
} else {
$message .= "'{$token['value']}' at position {$token['position']}";
}
if (strlen($this->context)) {
$message .= ' in ' . $this->context;
}
$message .= '.';
throw AnnotationException::syntaxError($message);
}
/**
* Annotations ::= Annotation {[ "*" ]* [Annotation]}*
*
* @return array
*/
public function Annotations()
{
$this->isNestedAnnotation = false;
$annotations = array();
$annot = $this->Annotation();
if ($annot !== false) {
$annotations[get_class($annot)] = $annot;
$this->lexer->skipUntil(Lexer::T_AT);
}
while ($this->lexer->lookahead !== null && $this->lexer->isNextToken(Lexer::T_AT)) {
$this->isNestedAnnotation = false;
$annot = $this->Annotation();
if ($annot !== false) {
$annotations[get_class($annot)] = $annot;
$this->lexer->skipUntil(Lexer::T_AT);
}
}
return $annotations;
}
/**
* Annotation ::= "@" AnnotationName ["(" [Values] ")"]
* AnnotationName ::= QualifiedName | SimpleName | AliasedName
* QualifiedName ::= NameSpacePart "\" {NameSpacePart "\"}* SimpleName
* AliasedName ::= Alias ":" SimpleName
* NameSpacePart ::= identifier
* SimpleName ::= identifier
* Alias ::= identifier
*
* @return mixed False if it is not a valid annotation.
*/
public function Annotation()
{
$values = array();
$nameParts = array();
$this->match(Lexer::T_AT);
$this->match(Lexer::T_IDENTIFIER);
$nameParts[] = $this->lexer->token['value'];
while ($this->lexer->isNextToken(Lexer::T_NAMESPACE_SEPARATOR)) {
$this->match(Lexer::T_NAMESPACE_SEPARATOR);
$this->match(Lexer::T_IDENTIFIER);
$nameParts[] = $this->lexer->token['value'];
}
// Effectively pick the name of the class (append default NS if none, grab from NS alias, etc)
if (strpos($nameParts[0], ':')) {
list ($alias, $nameParts[0]) = explode(':', $nameParts[0]);
// If the namespace alias doesnt exist, skip until next annotation
if ( ! isset($this->namespaceAliases[$alias])) {
$this->lexer->skipUntil(Lexer::T_AT);
return false;
}
$name = $this->namespaceAliases[$alias] . implode('\\', $nameParts);
} else if (count($nameParts) == 1) {
$name = $this->defaultAnnotationNamespace . $nameParts[0];
} else {
$name = implode('\\', $nameParts);
}
// Does the annotation class exist?
if ( ! class_exists($name, $this->autoloadAnnotations)) {
$this->lexer->skipUntil(Lexer::T_AT);
return false;
}
// Next will be nested
$this->isNestedAnnotation = true;
if ($this->lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS)) {
$this->match(Lexer::T_OPEN_PARENTHESIS);
if ( ! $this->lexer->isNextToken(Lexer::T_CLOSE_PARENTHESIS)) {
$values = $this->Values();
}
$this->match(Lexer::T_CLOSE_PARENTHESIS);
}
if ($this->annotationCreationFunction !== null) {
$func = $this->annotationCreationFunction;
$annot = $func($name, $values);
}
return isset($annot) ? $annot : $this->newAnnotation($name, $values);
}
/**
* Values ::= Array | Value {"," Value}*
*
* @return array
*/
public function Values()
{
$values = array();
// Handle the case of a single array as value, i.e. @Foo({....})
if ($this->lexer->isNextToken(Lexer::T_OPEN_CURLY_BRACES)) {
$values['value'] = $this->Value();
return $values;
}
$values[] = $this->Value();
while ($this->lexer->isNextToken(Lexer::T_COMMA)) {
$this->match(Lexer::T_COMMA);
$value = $this->Value();
if ( ! is_array($value)) {
$this->syntaxError('Value', $value);
}
$values[] = $value;
}
foreach ($values as $k => $value) {
if (is_array($value) && is_string(key($value))) {
$key = key($value);
$values[$key] = $value[$key];
} else {
$values['value'] = $value;
}
unset($values[$k]);
}
return $values;
}
/**
* Value ::= PlainValue | FieldAssignment
*
* @return mixed
*/
public function Value()
{
$peek = $this->lexer->glimpse();
if ($peek['value'] === '=') {
return $this->FieldAssignment();
}
return $this->PlainValue();
}
/**
* PlainValue ::= integer | string | float | boolean | Array | Annotation
*
* @return mixed
*/
public function PlainValue()
{
if ($this->lexer->isNextToken(Lexer::T_OPEN_CURLY_BRACES)) {
return $this->Arrayx();
}
if ($this->lexer->isNextToken(Lexer::T_AT)) {
return $this->Annotation();
}
switch ($this->lexer->lookahead['type']) {
case Lexer::T_STRING:
$this->match(Lexer::T_STRING);
return $this->lexer->token['value'];
case Lexer::T_INTEGER:
$this->match(Lexer::T_INTEGER);
return $this->lexer->token['value'];
case Lexer::T_FLOAT:
$this->match(Lexer::T_FLOAT);
return $this->lexer->token['value'];
case Lexer::T_TRUE:
$this->match(Lexer::T_TRUE);
return true;
case Lexer::T_FALSE:
$this->match(Lexer::T_FALSE);
return false;
default:
$this->syntaxError('PlainValue');
}
}
/**
* FieldAssignment ::= FieldName "=" PlainValue
* FieldName ::= identifier
*
* @return array
*/
public function FieldAssignment()
{
$this->match(Lexer::T_IDENTIFIER);
$fieldName = $this->lexer->token['value'];
$this->match(Lexer::T_EQUALS);
return array($fieldName => $this->PlainValue());
}
/**
* Array ::= "{" ArrayEntry {"," ArrayEntry}* "}"
*
* @return array
*/
public function Arrayx()
{
$array = $values = array();
$this->match(Lexer::T_OPEN_CURLY_BRACES);
$values[] = $this->ArrayEntry();
while ($this->lexer->isNextToken(Lexer::T_COMMA)) {
$this->match(Lexer::T_COMMA);
$values[] = $this->ArrayEntry();
}
$this->match(Lexer::T_CLOSE_CURLY_BRACES);
foreach ($values as $value) {
list ($key, $val) = $value;
if ($key !== null) {
$array[$key] = $val;
} else {
$array[] = $val;
}
}
return $array;
}
/**
* ArrayEntry ::= Value | KeyValuePair
* KeyValuePair ::= Key "=" PlainValue
* Key ::= string | integer
*
* @return array
*/
public function ArrayEntry()
{
$peek = $this->lexer->glimpse();
if ($peek['value'] == '=') {
$this->match(
$this->lexer->isNextToken(Lexer::T_INTEGER) ? Lexer::T_INTEGER : Lexer::T_STRING
);
$key = $this->lexer->token['value'];
$this->match(Lexer::T_EQUALS);
return array($key, $this->PlainValue());
}
return array(null, $this->Value());
}
/**
* Constructs a new annotation with a given map of values.
*
* The default construction procedure is to instantiate a new object of a class
* with the same name as the annotation. Subclasses can override this method to
* change the construction process of new annotations.
*
* @param string The name of the annotation.
* @param array The map of annotation values.
* @return mixed The new annotation with the given values.
*/
protected function newAnnotation($name, array $values)
{
return new $name($values);
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Annotations;
/**
* Simple lexer for docblock annotations.
*
* This Lexer can be subclassed to customize certain aspects of the annotation
* lexing (token recognition) process. Note though that currently no special care
* is taken to maintain full backwards compatibility for subclasses. Implementation
* details of the default Lexer can change without explicit notice.
*
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class Lexer extends \Doctrine\Common\Lexer
{
const T_NONE = 1;
const T_IDENTIFIER = 2;
const T_INTEGER = 3;
const T_STRING = 4;
const T_FLOAT = 5;
const T_AT = 101;
const T_CLOSE_CURLY_BRACES = 102;
const T_CLOSE_PARENTHESIS = 103;
const T_COMMA = 104;
const T_EQUALS = 105;
const T_FALSE = 106;
const T_NAMESPACE_SEPARATOR = 107;
const T_OPEN_CURLY_BRACES = 108;
const T_OPEN_PARENTHESIS = 109;
const T_TRUE = 110;
/**
* @inheritdoc
*/
protected function getCatchablePatterns()
{
return array(
'[a-z_][a-z0-9_:]*',
'(?:[0-9]+(?:[\.][0-9]+)*)(?:e[+-]?[0-9]+)?',
'"(?:[^"]|"")*"'
);
}
/**
* @inheritdoc
*/
protected function getNonCatchablePatterns()
{
return array('\s+', '\*+', '(.)');
}
/**
* @inheritdoc
*/
protected function getType(&$value)
{
$type = self::T_NONE;
$newVal = $this->getNumeric($value);
// Checking numeric value
if ($newVal !== false) {
$value = $newVal;
return (strpos($value, '.') !== false || stripos($value, 'e') !== false)
? self::T_FLOAT : self::T_INTEGER;
}
if ($value[0] === '"') {
$value = str_replace('""', '"', substr($value, 1, strlen($value) - 2));
return self::T_STRING;
} else {
switch (strtolower($value)) {
case '@':
return self::T_AT;
case ',':
return self::T_COMMA;
case '(':
return self::T_OPEN_PARENTHESIS;
case ')':
return self::T_CLOSE_PARENTHESIS;
case '{':
return self::T_OPEN_CURLY_BRACES;
case '}': return self::T_CLOSE_CURLY_BRACES;
case '=':
return self::T_EQUALS;
case '\\':
return self::T_NAMESPACE_SEPARATOR;
case 'true':
return self::T_TRUE;
case 'false':
return self::T_FALSE;
default:
if (ctype_alpha($value[0]) || $value[0] === '_') {
return self::T_IDENTIFIER;
}
break;
}
}
return $type;
}
/**
* Checks if a value is numeric or not
*
* @param mixed $value Value to be inspected
* @return boolean|integer|float Processed value
* @todo Inline
*/
private function getNumeric($value)
{
if ( ! is_scalar($value)) {
return false;
}
// Checking for valid numeric numbers: 1.234, -1.234e-2
if (is_numeric($value)) {
return $value;
}
return false;
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Annotations;
/**
* Annotations class
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class Annotation
{
/**
* Value property. Common among all derived classes.
*
* @var string
*/
public $value;
/**
* Constructor
*
* @param array $data Key-value for properties to be defined in this class
*/
public final function __construct(array $data)
{
foreach ($data as $key => $value) {
$this->$key = $value;
}
}
/**
* Error handler for unknown property accessor in Annotation class.
*
* @param string $name Unknown property name
*/
public function __get($name)
{
throw new \BadMethodCallException(
sprintf("Unknown property '%s' on annotation '%s'.", $name, get_class($this))
);
}
/**
* Error handler for unknown property mutator in Annotation class.
*
* @param string $name Unkown property name
* @param mixed $value Property value
*/
public function __set($name, $value)
{
throw new \BadMethodCallException(
sprintf("Unknown property '%s' on annotation '%s'.", $name, get_class($this))
);
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common;
/**
* A <tt>ClassLoader</tt> is an autoloader for class files that can be
* installed on the SPL autoload stack. It is a class loader that either loads only classes
* of a specific namespace or all namespaces and it is suitable for working together
* with other autoloaders in the SPL autoload stack.
*
* If no include path is configured through the constructor or {@link setIncludePath}, a ClassLoader
* relies on the PHP <code>include_path</code>.
*
* @author Roman Borschel <roman@code-factory.org>
* @since 2.0
*/
class ClassLoader
{
private $fileExtension = '.php';
private $namespace;
private $includePath;
private $namespaceSeparator = '\\';
/**
* Creates a new <tt>ClassLoader</tt> that loads classes of the
* specified namespace from the specified include path.
*
* If no include path is given, the ClassLoader relies on the PHP include_path.
* If neither a namespace nor an include path is given, the ClassLoader will
* be responsible for loading all classes, thereby relying on the PHP include_path.
*
* @param string $ns The namespace of the classes to load.
* @param string $includePath The base include path to use.
*/
public function __construct($ns = null, $includePath = null)
{
$this->namespace = $ns;
$this->includePath = $includePath;
}
/**
* Sets the namespace separator used by classes in the namespace of this ClassLoader.
*
* @param string $sep The separator to use.
*/
public function setNamespaceSeparator($sep)
{
$this->namespaceSeparator = $sep;
}
/**
* Gets the namespace separator used by classes in the namespace of this ClassLoader.
*
* @return string
*/
public function getNamespaceSeparator()
{
return $this->namespaceSeparator;
}
/**
* Sets the base include path for all class files in the namespace of this ClassLoader.
*
* @param string $includePath
*/
public function setIncludePath($includePath)
{
$this->includePath = $includePath;
}
/**
* Gets the base include path for all class files in the namespace of this ClassLoader.
*
* @return string
*/
public function getIncludePath()
{
return $this->includePath;
}
/**
* Sets the file extension of class files in the namespace of this ClassLoader.
*
* @param string $fileExtension
*/
public function setFileExtension($fileExtension)
{
$this->fileExtension = $fileExtension;
}
/**
* Gets the file extension of class files in the namespace of this ClassLoader.
*
* @return string
*/
public function getFileExtension()
{
return $this->fileExtension;
}
/**
* Registers this ClassLoader on the SPL autoload stack.
*/
public function register()
{
spl_autoload_register(array($this, 'loadClass'));
}
/**
* Removes this ClassLoader from the SPL autoload stack.
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
}
/**
* Loads the given class or interface.
*
* @param string $classname The name of the class to load.
* @return boolean TRUE if the class has been successfully loaded, FALSE otherwise.
*/
public function loadClass($className)
{
if ($this->namespace !== null && strpos($className, $this->namespace.$this->namespaceSeparator) !== 0) {
return false;
}
require ($this->includePath !== null ? $this->includePath . DIRECTORY_SEPARATOR : '')
. str_replace($this->namespaceSeparator, DIRECTORY_SEPARATOR, $className)
. $this->fileExtension;
return true;
}
/**
* Asks this ClassLoader whether it can potentially load the class (file) with
* the given name.
*
* @param string $className The fully-qualified name of the class.
* @return boolean TRUE if this ClassLoader can load the class, FALSE otherwise.
*/
public function canLoadClass($className)
{
if ($this->namespace !== null && strpos($className, $this->namespace.$this->namespaceSeparator) !== 0) {
return false;
}
return file_exists(($this->includePath !== null ? $this->includePath . DIRECTORY_SEPARATOR : '')
. str_replace($this->namespaceSeparator, DIRECTORY_SEPARATOR, $className)
. $this->fileExtension);
}
/**
* Checks whether a class with a given name exists. A class "exists" if it is either
* already defined in the current request or if there is an autoloader on the SPL
* autoload stack that is a) responsible for the class in question and b) is able to
* load a class file in which the class definition resides.
*
* If the class is not already defined, each autoloader in the SPL autoload stack
* is asked whether it is able to tell if the class exists. If the autoloader is
* a <tt>ClassLoader</tt>, {@link canLoadClass} is used, otherwise the autoload
* function of the autoloader is invoked and expected to return a value that
* evaluates to TRUE if the class (file) exists. As soon as one autoloader reports
* that the class exists, TRUE is returned.
*
* Note that, depending on what kinds of autoloaders are installed on the SPL
* autoload stack, the class (file) might already be loaded as a result of checking
* for its existence. This is not the case with a <tt>ClassLoader</tt>, who separates
* these responsibilities.
*
* @param string $className The fully-qualified name of the class.
* @return boolean TRUE if the class exists as per the definition given above, FALSE otherwise.
*/
public static function classExists($className)
{
if (class_exists($className, false)) {
return true;
}
foreach (spl_autoload_functions() as $loader) {
if (is_array($loader)) { // array(???, ???)
if (is_object($loader[0])) {
if ($loader[0] instanceof ClassLoader) { // array($obj, 'methodName')
if ($loader[0]->canLoadClass($className)) {
return true;
}
} else if ($loader[0]->{$loader[1]}($className)) {
return true;
}
} else if ($loader[0]::$loader[1]($className)) { // array('ClassName', 'methodName')
return true;
}
} else if ($loader instanceof \Closure) { // function($className) {..}
if ($loader($className)) {
return true;
}
} else if (is_string($loader) && $loader($className)) { // "MyClass::loadClass"
return true;
}
}
return false;
}
/**
* Gets the <tt>ClassLoader</tt> from the SPL autoload stack that is responsible
* for (and is able to load) the class with the given name.
*
* @param string $className The name of the class.
* @return The <tt>ClassLoader</tt> for the class or NULL if no such <tt>ClassLoader</tt> exists.
*/
public static function getClassLoader($className)
{
foreach (spl_autoload_functions() as $loader) {
if (is_array($loader) && $loader[0] instanceof ClassLoader &&
$loader[0]->canLoadClass($className)) {
return $loader[0];
}
}
return null;
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Collections;
use Closure, ArrayIterator;
/**
* An ArrayCollection is a Collection implementation that wraps a regular PHP array.
*
* @since 2.0
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class ArrayCollection implements Collection
{
/**
* An array containing the entries of this collection.
*
* @var array
*/
private $_elements;
/**
* Initializes a new ArrayCollection.
*
* @param array $elements
*/
public function __construct(array $elements = array())
{
$this->_elements = $elements;
}
/**
* Gets the PHP array representation of this collection.
*
* @return array The PHP array representation of this collection.
*/
public function toArray()
{
return $this->_elements;
}
/**
* Sets the internal iterator to the first element in the collection and
* returns this element.
*
* @return mixed
*/
public function first()
{
return reset($this->_elements);
}
/**
* Sets the internal iterator to the last element in the collection and
* returns this element.
*
* @return mixed
*/
public function last()
{
return end($this->_elements);
}
/**
* Gets the current key/index at the current internal iterator position.
*
* @return mixed
*/
public function key()
{
return key($this->_elements);
}
/**
* Moves the internal iterator position to the next element.
*
* @return mixed
*/
public function next()
{
return next($this->_elements);
}
/**
* Gets the element of the collection at the current internal iterator position.
*
* @return mixed
*/
public function current()
{
return current($this->_elements);
}
/**
* Removes an element with a specific key/index from the collection.
*
* @param mixed $key
* @return mixed The removed element or NULL, if no element exists for the given key.
*/
public function remove($key)
{
if (isset($this->_elements[$key])) {
$removed = $this->_elements[$key];
unset($this->_elements[$key]);
return $removed;
}
return null;
}
/**
* Removes the specified element from the collection, if it is found.
*
* @param mixed $element The element to remove.
* @return boolean TRUE if this collection contained the specified element, FALSE otherwise.
*/
public function removeElement($element)
{
$key = array_search($element, $this->_elements, true);
if ($key !== false) {
unset($this->_elements[$key]);
return true;
}
return false;
}
/**
* ArrayAccess implementation of offsetExists()
*
* @see containsKey()
*/
public function offsetExists($offset)
{
return $this->containsKey($offset);
}
/**
* ArrayAccess implementation of offsetGet()
*
* @see get()
*/
public function offsetGet($offset)
{
return $this->get($offset);
}
/**
* ArrayAccess implementation of offsetGet()
*
* @see add()
* @see set()
*/
public function offsetSet($offset, $value)
{
if ( ! isset($offset)) {
return $this->add($value);
}
return $this->set($offset, $value);
}
/**
* ArrayAccess implementation of offsetUnset()
*
* @see remove()
*/
public function offsetUnset($offset)
{
return $this->remove($offset);
}
/**
* Checks whether the collection contains a specific key/index.
*
* @param mixed $key The key to check for.
* @return boolean TRUE if the given key/index exists, FALSE otherwise.
*/
public function containsKey($key)
{
return isset($this->_elements[$key]);
}
/**
* Checks whether the given element is contained in the collection.
* Only element values are compared, not keys. The comparison of two elements
* is strict, that means not only the value but also the type must match.
* For objects this means reference equality.
*
* @param mixed $element
* @return boolean TRUE if the given element is contained in the collection,
* FALSE otherwise.
*/
public function contains($element)
{
return in_array($element, $this->_elements, true);
}
/**
* Tests for the existance of an element that satisfies the given predicate.
*
* @param Closure $p The predicate.
* @return boolean TRUE if the predicate is TRUE for at least one element, FALSE otherwise.
*/
public function exists(Closure $p)
{
foreach ($this->_elements as $key => $element)
if ($p($key, $element)) return true;
return false;
}
/**
* Searches for a given element and, if found, returns the corresponding key/index
* of that element. The comparison of two elements is strict, that means not
* only the value but also the type must match.
* For objects this means reference equality.
*
* @param mixed $element The element to search for.
* @return mixed The key/index of the element or FALSE if the element was not found.
*/
public function indexOf($element)
{
return array_search($element, $this->_elements, true);
}
/**
* Gets the element with the given key/index.
*
* @param mixed $key The key.
* @return mixed The element or NULL, if no element exists for the given key.
*/
public function get($key)
{
if (isset($this->_elements[$key])) {
return $this->_elements[$key];
}
return null;
}
/**
* Gets all keys/indexes of the collection elements.
*
* @return array
*/
public function getKeys()
{
return array_keys($this->_elements);
}
/**
* Gets all elements.
*
* @return array
*/
public function getValues()
{
return array_values($this->_elements);
}
/**
* Returns the number of elements in the collection.
*
* Implementation of the Countable interface.
*
* @return integer The number of elements in the collection.
*/
public function count()
{
return count($this->_elements);
}
/**
* Adds/sets an element in the collection at the index / with the specified key.
*
* When the collection is a Map this is like put(key,value)/add(key,value).
* When the collection is a List this is like add(position,value).
*
* @param mixed $key
* @param mixed $value
*/
public function set($key, $value)
{
$this->_elements[$key] = $value;
}
/**
* Adds an element to the collection.
*
* @param mixed $value
* @return boolean Always TRUE.
*/
public function add($value)
{
$this->_elements[] = $value;
return true;
}
/**
* Checks whether the collection is empty.
*
* Note: This is preferrable over count() == 0.
*
* @return boolean TRUE if the collection is empty, FALSE otherwise.
*/
public function isEmpty()
{
return ! $this->_elements;
}
/**
* Gets an iterator for iterating over the elements in the collection.
*
* @return ArrayIterator
*/
public function getIterator()
{
return new ArrayIterator($this->_elements);
}
/**
* Applies the given function to each element in the collection and returns
* a new collection with the elements returned by the function.
*
* @param Closure $func
* @return Collection
*/
public function map(Closure $func)
{
return new ArrayCollection(array_map($func, $this->_elements));
}
/**
* Returns all the elements of this collection that satisfy the predicate p.
* The order of the elements is preserved.
*
* @param Closure $p The predicate used for filtering.
* @return Collection A collection with the results of the filter operation.
*/
public function filter(Closure $p)
{
return new ArrayCollection(array_filter($this->_elements, $p));
}
/**
* Applies the given predicate p to all elements of this collection,
* returning true, if the predicate yields true for all elements.
*
* @param Closure $p The predicate.
* @return boolean TRUE, if the predicate yields TRUE for all elements, FALSE otherwise.
*/
public function forAll(Closure $p)
{
foreach ($this->_elements as $key => $element) {
if ( ! $p($key, $element)) {
return false;
}
}
return true;
}
/**
* Partitions this collection in two collections according to a predicate.
* Keys are preserved in the resulting collections.
*
* @param Closure $p The predicate on which to partition.
* @return array An array with two elements. The first element contains the collection
* of elements where the predicate returned TRUE, the second element
* contains the collection of elements where the predicate returned FALSE.
*/
public function partition(Closure $p)
{
$coll1 = $coll2 = array();
foreach ($this->_elements as $key => $element) {
if ($p($key, $element)) {
$coll1[$key] = $element;
} else {
$coll2[$key] = $element;
}
}
return array(new ArrayCollection($coll1), new ArrayCollection($coll2));
}
/**
* Returns a string representation of this object.
*
* @return string
*/
public function __toString()
{
return __CLASS__ . '@' . spl_object_hash($this);
}
/**
* Clears the collection.
*/
public function clear()
{
$this->_elements = array();
}
/**
* Extract a slice of $length elements starting at position $offset from the Collection.
*
* If $length is null it returns all elements from $offset to the end of the Collection.
* Keys have to be preserved by this method. Calling this method will only return the
* selected slice and NOT change the elements contained in the collection slice is called on.
*
* @param int $offset
* @param int $length
* @return array
*/
public function slice($offset, $length = null)
{
return array_slice($this->_elements, $offset, $length, true);
}
}
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Collections;
use Closure, Countable, IteratorAggregate, ArrayAccess;
/**
* The missing (SPL) Collection/Array/OrderedMap interface.
*
* A Collection resembles the nature of a regular PHP array. That is,
* it is essentially an <b>ordered map</b> that can also be used
* like a list.
*
* A Collection has an internal iterator just like a PHP array. In addition,
* a Collection can be iterated with external iterators, which is preferrable.
* To use an external iterator simply use the foreach language construct to
* iterate over the collection (which calls {@link getIterator()} internally) or
* explicitly retrieve an iterator though {@link getIterator()} which can then be
* used to iterate over the collection.
* You can not rely on the internal iterator of the collection being at a certain
* position unless you explicitly positioned it before. Prefer iteration with
* external iterators.
*
* @since 2.0
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
interface Collection extends Countable, IteratorAggregate, ArrayAccess
{
/**
* Adds an element at the end of the collection.
*
* @param mixed $element The element to add.
* @return boolean Always TRUE.
*/
function add($element);
/**
* Clears the collection, removing all elements.
*/
function clear();
/**
* Checks whether an element is contained in the collection.
* This is an O(n) operation, where n is the size of the collection.
*
* @param mixed $element The element to search for.
* @return boolean TRUE if the collection contains the element, FALSE otherwise.
*/
function contains($element);
/**
* Checks whether the collection is empty (contains no elements).
*
* @return boolean TRUE if the collection is empty, FALSE otherwise.
*/
function isEmpty();
/**
* Removes the element at the specified index from the collection.
*
* @param string|integer $key The kex/index of the element to remove.
* @return mixed The removed element or NULL, if the collection did not contain the element.
*/
function remove($key);
/**
* Removes the specified element from the collection, if it is found.
*
* @param mixed $element The element to remove.
* @return boolean TRUE if this collection contained the specified element, FALSE otherwise.
*/
function removeElement($element);
/**
* Checks whether the collection contains an element with the specified key/index.
*
* @param string|integer $key The key/index to check for.
* @return boolean TRUE if the collection contains an element with the specified key/index,
* FALSE otherwise.
*/
function containsKey($key);
/**
* Gets the element at the specified key/index.
*
* @param string|integer $key The key/index of the element to retrieve.
* @return mixed
*/
function get($key);
/**
* Gets all keys/indices of the collection.
*
* @return array The keys/indices of the collection, in the order of the corresponding
* elements in the collection.
*/
function getKeys();
/**
* Gets all values of the collection.
*
* @return array The values of all elements in the collection, in the order they
* appear in the collection.
*/
function getValues();
/**
* Sets an element in the collection at the specified key/index.
*
* @param string|integer $key The key/index of the element to set.
* @param mixed $value The element to set.
*/
function set($key, $value);
/**
* Gets a native PHP array representation of the collection.
*
* @return array
*/
function toArray();
/**
* Sets the internal iterator to the first element in the collection and
* returns this element.
*
* @return mixed
*/
function first();
/**
* Sets the internal iterator to the last element in the collection and
* returns this element.
*
* @return mixed
*/
function last();
/**
* Gets the key/index of the element at the current iterator position.
*
*/
function key();
/**
* Gets the element of the collection at the current iterator position.
*
*/
function current();
/**
* Moves the internal iterator position to the next element.
*
*/
function next();
/**
* Tests for the existence of an element that satisfies the given predicate.
*
* @param Closure $p The predicate.
* @return boolean TRUE if the predicate is TRUE for at least one element, FALSE otherwise.
*/
function exists(Closure $p);
/**
* Returns all the elements of this collection that satisfy the predicate p.
* The order of the elements is preserved.
*
* @param Closure $p The predicate used for filtering.
* @return Collection A collection with the results of the filter operation.
*/
function filter(Closure $p);
/**
* Applies the given predicate p to all elements of this collection,
* returning true, if the predicate yields true for all elements.
*
* @param Closure $p The predicate.
* @return boolean TRUE, if the predicate yields TRUE for all elements, FALSE otherwise.
*/
function forAll(Closure $p);
/**
* Applies the given function to each element in the collection and returns
* a new collection with the elements returned by the function.
*
* @param Closure $func
* @return Collection
*/
function map(Closure $func);
/**
* Partitions this collection in two collections according to a predicate.
* Keys are preserved in the resulting collections.
*
* @param Closure $p The predicate on which to partition.
* @return array An array with two elements. The first element contains the collection
* of elements where the predicate returned TRUE, the second element
* contains the collection of elements where the predicate returned FALSE.
*/
function partition(Closure $p);
/**
* Gets the index/key of a given element. The comparison of two elements is strict,
* that means not only the value but also the type must match.
* For objects this means reference equality.
*
* @param mixed $element The element to search for.
* @return mixed The key/index of the element or FALSE if the element was not found.
*/
function indexOf($element);
/**
* Extract a slice of $length elements starting at position $offset from the Collection.
*
* If $length is null it returns all elements from $offset to the end of the Collection.
* Keys have to be preserved by this method. Calling this method will only return the
* selected slice and NOT change the elements contained in the collection slice is called on.
*
* @param int $offset
* @param int $length
* @return array
*/
public function slice($offset, $length = null);
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common;
/**
* Class to store and retrieve the version of Doctrine
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class Version
{
/**
* Current Doctrine Version
*/
const VERSION = '2.0.0RC2-DEV';
/**
* Compares a Doctrine version with the current one.
*
* @param string $version Doctrine version to compare.
* @return int Returns -1 if older, 0 if it is the same, 1 if version
* passed as argument is newer.
*/
public static function compare($version)
{
$currentVersion = str_replace(' ', '', strtolower(self::VERSION));
$version = str_replace(' ', '', $version);
return version_compare($version, $currentVersion);
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Cache;
/**
* Xcache cache driver.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author David Abdemoulaie <dave@hobodave.com>
*/
class XcacheCache extends AbstractCache
{
/**
* {@inheritdoc}
*/
public function getIds()
{
$this->_checkAuth();
$keys = array();
for ($i = 0, $count = xcache_count(XC_TYPE_VAR); $i < $count; $i++) {
$entries = xcache_list(XC_TYPE_VAR, $i);
if (is_array($entries['cache_list'])) {
foreach ($entries['cache_list'] as $entry) {
$keys[] = $entry['name'];
}
}
}
return $keys;
}
/**
* {@inheritdoc}
*/
protected function _doFetch($id)
{
return $this->_doContains($id) ? unserialize(xcache_get($id)) : false;
}
/**
* {@inheritdoc}
*/
protected function _doContains($id)
{
return xcache_isset($id);
}
/**
* {@inheritdoc}
*/
protected function _doSave($id, $data, $lifeTime = 0)
{
return xcache_set($id, serialize($data), (int) $lifeTime);
}
/**
* {@inheritdoc}
*/
protected function _doDelete($id)
{
return xcache_unset($id);
}
/**
* Checks that xcache.admin.enable_auth is Off
*
* @throws \BadMethodCallException When xcache.admin.enable_auth is On
* @return void
*/
protected function _checkAuth()
{
if (ini_get('xcache.admin.enable_auth')) {
throw new \BadMethodCallException('To use all features of \Doctrine\Common\Cache\XcacheCache, you must set "xcache.admin.enable_auth" to "Off" in your php.ini.');
}
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Cache;
/**
* Array cache driver.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author David Abdemoulaie <dave@hobodave.com>
*/
class ArrayCache extends AbstractCache
{
/**
* @var array $data
*/
private $data = array();
/**
* {@inheritdoc}
*/
public function getIds()
{
return array_keys($this->data);
}
/**
* {@inheritdoc}
*/
protected function _doFetch($id)
{
if (isset($this->data[$id])) {
return $this->data[$id];
}
return false;
}
/**
* {@inheritdoc}
*/
protected function _doContains($id)
{
return isset($this->data[$id]);
}
/**
* {@inheritdoc}
*/
protected function _doSave($id, $data, $lifeTime = 0)
{
$this->data[$id] = $data;
return true;
}
/**
* {@inheritdoc}
*/
protected function _doDelete($id)
{
unset($this->data[$id]);
return true;
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Cache;
use \Memcache;
/**
* Memcache cache driver.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author David Abdemoulaie <dave@hobodave.com>
*/
class MemcacheCache extends AbstractCache
{
/**
* @var Memcache
*/
private $_memcache;
/**
* Sets the memcache instance to use.
*
* @param Memcache $memcache
*/
public function setMemcache(Memcache $memcache)
{
$this->_memcache = $memcache;
}
/**
* Gets the memcache instance used by the cache.
*
* @return Memcache
*/
public function getMemcache()
{
return $this->_memcache;
}
/**
* {@inheritdoc}
*/
public function getIds()
{
$keys = array();
$allSlabs = $this->_memcache->getExtendedStats('slabs');
foreach ($allSlabs as $server => $slabs) {
if (is_array($slabs)) {
foreach (array_keys($slabs) as $slabId) {
$dump = $this->_memcache->getExtendedStats('cachedump', (int) $slabId);
if ($dump) {
foreach ($dump as $entries) {
if ($entries) {
$keys = array_merge($keys, array_keys($entries));
}
}
}
}
}
}
return $keys;
}
/**
* {@inheritdoc}
*/
protected function _doFetch($id)
{
return $this->_memcache->get($id);
}
/**
* {@inheritdoc}
*/
protected function _doContains($id)
{
return (bool) $this->_memcache->get($id);
}
/**
* {@inheritdoc}
*/
protected function _doSave($id, $data, $lifeTime = 0)
{
return $this->_memcache->set($id, $data, 0, (int) $lifeTime);
}
/**
* {@inheritdoc}
*/
protected function _doDelete($id)
{
return $this->_memcache->delete($id);
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Cache;
/**
* Interface for cache drivers.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
interface Cache
{
/**
* Fetches an entry from the cache.
*
* @param string $id cache id The id of the cache entry to fetch.
* @return string The cached data or FALSE, if no cache entry exists for the given id.
*/
function fetch($id);
/**
* Test if an entry exists in the cache.
*
* @param string $id cache id The cache id of the entry to check for.
* @return boolean TRUE if a cache entry exists for the given cache id, FALSE otherwise.
*/
function contains($id);
/**
* Puts data into the cache.
*
* @param string $id The cache id.
* @param string $data The cache entry/data.
* @param int $lifeTime The lifetime. If != 0, sets a specific lifetime for this cache entry (0 => infinite lifeTime).
* @return boolean TRUE if the entry was successfully stored in the cache, FALSE otherwise.
*/
function save($id, $data, $lifeTime = 0);
/**
* Deletes a cache entry.
*
* @param string $id cache id
* @return boolean TRUE if the cache entry was successfully deleted, FALSE otherwise.
*/
function delete($id);
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Cache;
/**
* APC cache driver.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author David Abdemoulaie <dave@hobodave.com>
* @todo Rename: APCCache
*/
class ApcCache extends AbstractCache
{
/**
* {@inheritdoc}
*/
public function getIds()
{
$ci = apc_cache_info('user');
$keys = array();
foreach ($ci['cache_list'] as $entry) {
$keys[] = $entry['info'];
}
return $keys;
}
/**
* {@inheritdoc}
*/
protected function _doFetch($id)
{
return apc_fetch($id);
}
/**
* {@inheritdoc}
*/
protected function _doContains($id)
{
$found = false;
apc_fetch($id, $found);
return $found;
}
/**
* {@inheritdoc}
*/
protected function _doSave($id, $data, $lifeTime = 0)
{
return (bool) apc_store($id, $data, (int) $lifeTime);
}
/**
* {@inheritdoc}
*/
protected function _doDelete($id)
{
return apc_delete($id);
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Cache;
/**
* Base class for cache driver implementations.
*
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
abstract class AbstractCache implements Cache
{
/** @var string The cache id to store the index of cache ids under */
private $_cacheIdsIndexId = 'doctrine_cache_ids';
/** @var string The namespace to prefix all cache ids with */
private $_namespace = null;
/**
* Set the namespace to prefix all cache ids with.
*
* @param string $namespace
* @return void
*/
public function setNamespace($namespace)
{
$this->_namespace = $namespace;
}
/**
* {@inheritdoc}
*/
public function fetch($id)
{
return $this->_doFetch($this->_getNamespacedId($id));
}
/**
* {@inheritdoc}
*/
public function contains($id)
{
return $this->_doContains($this->_getNamespacedId($id));
}
/**
* {@inheritdoc}
*/
public function save($id, $data, $lifeTime = 0)
{
return $this->_doSave($this->_getNamespacedId($id), $data, $lifeTime);
}
/**
* {@inheritdoc}
*/
public function delete($id)
{
$id = $this->_getNamespacedId($id);
if (strpos($id, '*') !== false) {
return $this->deleteByRegex('/' . str_replace('*', '.*', $id) . '/');
}
return $this->_doDelete($id);
}
/**
* Delete all cache entries.
*
* @return array $deleted Array of the deleted cache ids
*/
public function deleteAll()
{
$ids = $this->getIds();
foreach ($ids as $id) {
$this->delete($id);
}
return $ids;
}
/**
* Delete cache entries where the id matches a PHP regular expressions
*
* @param string $regex
* @return array $deleted Array of the deleted cache ids
*/
public function deleteByRegex($regex)
{
$deleted = array();
$ids = $this->getIds();
foreach ($ids as $id) {
if (preg_match($regex, $id)) {
$this->delete($id);
$deleted[] = $id;
}
}
return $deleted;
}
/**
* Delete cache entries where the id has the passed prefix
*
* @param string $prefix
* @return array $deleted Array of the deleted cache ids
*/
public function deleteByPrefix($prefix)
{
$deleted = array();
$prefix = $this->_getNamespacedId($prefix);
$ids = $this->getIds();
foreach ($ids as $id) {
if (strpos($id, $prefix) === 0) {
$this->delete($id);
$deleted[] = $id;
}
}
return $deleted;
}
/**
* Delete cache entries where the id has the passed suffix
*
* @param string $suffix
* @return array $deleted Array of the deleted cache ids
*/
public function deleteBySuffix($suffix)
{
$deleted = array();
$ids = $this->getIds();
foreach ($ids as $id) {
if (substr($id, -1 * strlen($suffix)) === $suffix) {
$this->delete($id);
$deleted[] = $id;
}
}
return $deleted;
}
/**
* Prefix the passed id with the configured namespace value
*
* @param string $id The id to namespace
* @return string $id The namespaced id
*/
private function _getNamespacedId($id)
{
if ( ! $this->_namespace || strpos($id, $this->_namespace) === 0) {
return $id;
} else {
return $this->_namespace . $id;
}
}
/**
* Fetches an entry from the cache.
*
* @param string $id cache id The id of the cache entry to fetch.
* @return string The cached data or FALSE, if no cache entry exists for the given id.
*/
abstract protected function _doFetch($id);
/**
* Test if an entry exists in the cache.
*
* @param string $id cache id The cache id of the entry to check for.
* @return boolean TRUE if a cache entry exists for the given cache id, FALSE otherwise.
*/
abstract protected function _doContains($id);
/**
* Puts data into the cache.
*
* @param string $id The cache id.
* @param string $data The cache entry/data.
* @param int $lifeTime The lifetime. If != false, sets a specific lifetime for this cache entry (null => infinite lifeTime).
* @return boolean TRUE if the entry was successfully stored in the cache, FALSE otherwise.
*/
abstract protected function _doSave($id, $data, $lifeTime = false);
/**
* Deletes a cache entry.
*
* @param string $id cache id
* @return boolean TRUE if the cache entry was successfully deleted, FALSE otherwise.
*/
abstract protected function _doDelete($id);
/**
* Get an array of all the cache ids stored
*
* @return array $ids
*/
abstract public function getIds();
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Util;
/**
* Static class containing most used debug methods.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author Giorgio Sironi <piccoloprincipeazzurro@gmail.com>
*/
final class Debug
{
/**
* Private constructor (prevents from instantiation)
*
*/
private function __construct() {}
/**
* Prints a dump of the public, protected and private properties of $var.
*
* @static
* @link http://xdebug.org/
* @param mixed $var
* @param integer $maxDepth Maximum nesting level for object properties
*/
public static function dump($var, $maxDepth = 2)
{
ini_set('html_errors', 'On');
if (extension_loaded('xdebug')) {
ini_set('xdebug.var_display_max_depth', $maxDepth);
}
$var = self::export($var, $maxDepth++);
ob_start();
var_dump($var);
$dump = ob_get_contents();
ob_end_clean();
echo strip_tags(html_entity_decode($dump));
ini_set('html_errors', 'Off');
}
public static function export($var, $maxDepth)
{
$return = null;
$isObj = is_object($var);
if ($isObj && in_array('Doctrine\Common\Collections\Collection', class_implements($var))) {
$var = $var->toArray();
}
if ($maxDepth) {
if (is_array($var)) {
$return = array();
foreach ($var as $k => $v) {
$return[$k] = self::export($v, $maxDepth - 1);
}
} else if ($isObj) {
if ($var instanceof \DateTime) {
$return = $var->format('c');
} else {
$reflClass = new \ReflectionClass(get_class($var));
$return = new \stdclass();
$return->{'__CLASS__'} = get_class($var);
if ($var instanceof \Doctrine\ORM\Proxy\Proxy && ! $var->__isInitialized__) {
$reflProperty = $reflClass->getProperty('_identifier');
$reflProperty->setAccessible(true);
foreach ($reflProperty->getValue($var) as $name => $value) {
$return->$name = self::export($value, $maxDepth - 1);
}
} else {
$excludeProperties = array();
if ($var instanceof \Doctrine\ORM\Proxy\Proxy) {
$excludeProperties = array('_entityPersister', '__isInitialized__', '_identifier');
}
foreach ($reflClass->getProperties() as $reflProperty) {
$name = $reflProperty->getName();
if ( ! in_array($name, $excludeProperties)) {
$reflProperty->setAccessible(true);
$return->$name = self::export($reflProperty->getValue($var), $maxDepth - 1);
}
}
}
}
} else {
$return = $var;
}
} else {
$return = is_object($var) ? get_class($var)
: (is_array($var) ? 'Array(' . count($var) . ')' : $var);
}
return $return;
}
public static function toString($obj)
{
return method_exists('__toString', $obj) ? (string) $obj : get_class($obj) . '@' . spl_object_hash($obj);
}
}
<?php
/*
* $Id: Inflector.php 3189 2007-11-18 20:37:44Z meus $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common\Util;
/**
* Doctrine inflector has static methods for inflecting text
*
* The methods in these classes are from several different sources collected
* across several different php projects and several different authors. The
* original author names and emails are not known
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 1.0
* @version $Revision: 3189 $
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Jonathan H. Wage <jonwage@gmail.com>
*/
class Inflector
{
/**
* Convert word in to the format for a Doctrine table name. Converts 'ModelName' to 'model_name'
*
* @param string $word Word to tableize
* @return string $word Tableized word
*/
public static function tableize($word)
{
return strtolower(preg_replace('~(?<=\\w)([A-Z])~', '_$1', $word));
}
/**
* Convert a word in to the format for a Doctrine class name. Converts 'table_name' to 'TableName'
*
* @param string $word Word to classify
* @return string $word Classified word
*/
public static function classify($word)
{
return str_replace(" ", "", ucwords(strtr($word, "_-", " ")));
}
/**
* Camelize a word. This uses the classify() method and turns the first character to lowercase
*
* @param string $word
* @return string $word
*/
public static function camelize($word)
{
return lcfirst(self::classify($word));
}
}<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common;
/**
* Contract for classes that provide the service of notifying listeners of
* changes to their properties.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
interface NotifyPropertyChanged
{
/**
* Adds a listener that wants to be notified about property changes.
*
* @param PropertyChangedListener $listener
*/
function addPropertyChangedListener(PropertyChangedListener $listener);
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common;
/**
* Contract for classes that are potential listeners of a <tt>NotifyPropertyChanged</tt>
* implementor.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
interface PropertyChangedListener
{
/**
* Notifies the listener of a property change.
*
* @param object $sender The object on which the property changed.
* @param string $propertyName The name of the property that changed.
* @param mixed $oldValue The old value of the property that changed.
* @param mixed $newValue The new value of the property that changed.
*/
function propertyChanged($sender, $propertyName, $oldValue, $newValue);
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common;
use Doctrine\Common\Events\Event;
/**
* The EventManager is the central point of Doctrine's event listener system.
* Listeners are registered on the manager and events are dispatched through the
* manager.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class EventManager
{
/**
* Map of registered listeners.
* <event> => <listeners>
*
* @var array
*/
private $_listeners = array();
/**
* Dispatches an event to all registered listeners.
*
* @param string $eventName The name of the event to dispatch. The name of the event is
* the name of the method that is invoked on listeners.
* @param EventArgs $eventArgs The event arguments to pass to the event handlers/listeners.
* If not supplied, the single empty EventArgs instance is used.
* @return boolean
*/
public function dispatchEvent($eventName, EventArgs $eventArgs = null)
{
if (isset($this->_listeners[$eventName])) {
$eventArgs = $eventArgs === null ? EventArgs::getEmptyInstance() : $eventArgs;
foreach ($this->_listeners[$eventName] as $listener) {
$listener->$eventName($eventArgs);
}
}
}
/**
* Gets the listeners of a specific event or all listeners.
*
* @param string $event The name of the event.
* @return array The event listeners for the specified event, or all event listeners.
*/
public function getListeners($event = null)
{
return $event ? $this->_listeners[$event] : $this->_listeners;
}
/**
* Checks whether an event has any registered listeners.
*
* @param string $event
* @return boolean TRUE if the specified event has any listeners, FALSE otherwise.
*/
public function hasListeners($event)
{
return isset($this->_listeners[$event]) && $this->_listeners[$event];
}
/**
* Adds an event listener that listens on the specified events.
*
* @param string|array $events The event(s) to listen on.
* @param object $listener The listener object.
*/
public function addEventListener($events, $listener)
{
// Picks the hash code related to that listener
$hash = spl_object_hash($listener);
foreach ((array) $events as $event) {
// Overrides listener if a previous one was associated already
// Prevents duplicate listeners on same event (same instance only)
$this->_listeners[$event][$hash] = $listener;
}
}
/**
* Removes an event listener from the specified events.
*
* @param string|array $events
* @param object $listener
*/
public function removeEventListener($events, $listener)
{
// Picks the hash code related to that listener
$hash = spl_object_hash($listener);
foreach ((array) $events as $event) {
// Check if actually have this listener associated
if (isset($this->_listeners[$event][$hash])) {
unset($this->_listeners[$event][$hash]);
}
}
}
/**
* Adds an EventSubscriber. The subscriber is asked for all the events he is
* interested in and added as a listener for these events.
*
* @param Doctrine\Common\EventSubscriber $subscriber The subscriber.
*/
public function addEventSubscriber(EventSubscriber $subscriber)
{
$this->addEventListener($subscriber->getSubscribedEvents(), $subscriber);
}
}<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common;
/**
* Base class for writing simple lexers, i.e. for creating small DSLs.
*
* @since 2.0
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @todo Rename: AbstractLexer
*/
abstract class Lexer
{
/**
* @var array Array of scanned tokens
*/
private $tokens = array();
/**
* @var integer Current lexer position in input string
*/
private $position = 0;
/**
* @var integer Current peek of current lexer position
*/
private $peek = 0;
/**
* @var array The next token in the input.
*/
public $lookahead;
/**
* @var array The last matched/seen token.
*/
public $token;
/**
* Sets the input data to be tokenized.
*
* The Lexer is immediately reset and the new input tokenized.
* Any unprocessed tokens from any previous input are lost.
*
* @param string $input The input to be tokenized.
*/
public function setInput($input)
{
$this->tokens = array();
$this->reset();
$this->scan($input);
}
/**
* Resets the lexer.
*/
public function reset()
{
$this->lookahead = null;
$this->token = null;
$this->peek = 0;
$this->position = 0;
}
/**
* Resets the peek pointer to 0.
*/
public function resetPeek()
{
$this->peek = 0;
}
/**
* Resets the lexer position on the input to the given position.
*
* @param integer $position Position to place the lexical scanner
*/
public function resetPosition($position = 0)
{
$this->position = $position;
}
/**
* Checks whether a given token matches the current lookahead.
*
* @param integer|string $token
* @return boolean
*/
public function isNextToken($token)
{
return $this->lookahead['type'] === $token;
}
/**
* Moves to the next token in the input string.
*
* A token is an associative array containing three items:
* - 'value' : the string value of the token in the input string
* - 'type' : the type of the token (identifier, numeric, string, input
* parameter, none)
* - 'position' : the position of the token in the input string
*
* @return array|null the next token; null if there is no more tokens left
*/
public function moveNext()
{
$this->peek = 0;
$this->token = $this->lookahead;
$this->lookahead = (isset($this->tokens[$this->position]))
? $this->tokens[$this->position++] : null;
return $this->lookahead !== null;
}
/**
* Tells the lexer to skip input tokens until it sees a token with the given value.
*
* @param $type The token type to skip until.
*/
public function skipUntil($type)
{
while ($this->lookahead !== null && $this->lookahead['type'] !== $type) {
$this->moveNext();
}
}
/**
* Checks if given value is identical to the given token
*
* @param mixed $value
* @param integer $token
* @return boolean
*/
public function isA($value, $token)
{
return $this->getType($value) === $token;
}
/**
* Moves the lookahead token forward.
*
* @return array | null The next token or NULL if there are no more tokens ahead.
*/
public function peek()
{
if (isset($this->tokens[$this->position + $this->peek])) {
return $this->tokens[$this->position + $this->peek++];
} else {
return null;
}
}
/**
* Peeks at the next token, returns it and immediately resets the peek.
*
* @return array|null The next token or NULL if there are no more tokens ahead.
*/
public function glimpse()
{
$peek = $this->peek();
$this->peek = 0;
return $peek;
}
/**
* Scans the input string for tokens.
*
* @param string $input a query string
*/
protected function scan($input)
{
static $regex;
if ( ! isset($regex)) {
$regex = '/(' . implode(')|(', $this->getCatchablePatterns()) . ')|'
. implode('|', $this->getNonCatchablePatterns()) . '/i';
}
$flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE;
$matches = preg_split($regex, $input, -1, $flags);
foreach ($matches as $match) {
// Must remain before 'value' assignment since it can change content
$type = $this->getType($match[0]);
$this->tokens[] = array(
'value' => $match[0],
'type' => $type,
'position' => $match[1],
);
}
}
/**
* Gets the literal for a given token.
*
* @param integer $token
* @return string
*/
public function getLiteral($token)
{
$className = get_class($this);
$reflClass = new \ReflectionClass($className);
$constants = $reflClass->getConstants();
foreach ($constants as $name => $value) {
if ($value === $token) {
return $className . '::' . $name;
}
}
return $token;
}
/**
* Lexical catchable patterns.
*
* @return array
*/
abstract protected function getCatchablePatterns();
/**
* Lexical non-catchable patterns.
*
* @return array
*/
abstract protected function getNonCatchablePatterns();
/**
* Retrieve token type. Also processes the token value if necessary.
*
* @param string $value
* @return integer
*/
abstract protected function getType(&$value);
}<?php
/*
* $Id: EventListener.php 4653 2008-07-10 17:17:58Z romanb $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Common;
/**
* An EventSubscriber knows himself what events he is interested in.
* If an EventSubscriber is added to an EventManager, the manager invokes
* {@link getSubscribedEvents} and registers the subscriber as a listener for all
* returned events.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
interface EventSubscriber
{
/**
* Returns an array of events this subscriber wants to listen to.
*
* @return array
*/
public function getSubscribedEvents();
}
<?php
namespace Symfony\Component\Yaml;
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Yaml offers convenience methods to load and dump YAML.
*
* @package symfony
* @subpackage yaml
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Yaml
{
static protected $spec = '1.2';
/**
* Sets the YAML specification version to use.
*
* @param string $version The YAML specification version
*/
static public function setSpecVersion($version)
{
if (!in_array($version, array('1.1', '1.2')))
{
throw new \InvalidArgumentException(sprintf('Version %s of the YAML specifications is not supported', $version));
}
self::$spec = $version;
}
/**
* Gets the YAML specification version to use.
*
* @return string The YAML specification version
*/
static public function getSpecVersion()
{
return self::$spec;
}
/**
* Loads YAML into a PHP array.
*
* The load method, when supplied with a YAML stream (string or file),
* will do its best to convert YAML in a file into a PHP array.
*
* Usage:
* <code>
* $array = Yaml::load('config.yml');
* print_r($array);
* </code>
*
* @param string $input Path of YAML file or string containing YAML
*
* @return array The YAML converted to a PHP array
*
* @throws \InvalidArgumentException If the YAML is not valid
*/
public static function load($input)
{
$file = '';
// if input is a file, process it
if (strpos($input, "\n") === false && is_file($input))
{
$file = $input;
ob_start();
$retval = include($input);
$content = ob_get_clean();
// if an array is returned by the config file assume it's in plain php form else in YAML
$input = is_array($retval) ? $retval : $content;
}
// if an array is returned by the config file assume it's in plain php form else in YAML
if (is_array($input))
{
return $input;
}
$yaml = new Parser();
try
{
$ret = $yaml->parse($input);
}
catch (\Exception $e)
{
throw new \InvalidArgumentException(sprintf('Unable to parse %s: %s', $file ? sprintf('file "%s"', $file) : 'string', $e->getMessage()));
}
return $ret;
}
/**
* Dumps a PHP array to a YAML string.
*
* The dump method, when supplied with an array, will do its best
* to convert the array into friendly YAML.
*
* @param array $array PHP array
* @param integer $inline The level where you switch to inline YAML
*
* @return string A YAML string representing the original PHP array
*/
public static function dump($array, $inline = 2)
{
$yaml = new Dumper();
return $yaml->dump($array, $inline);
}
}
<?php
namespace Symfony\Component\Yaml;
/*
* This file is part of the symfony package.
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Dumper dumps PHP variables to YAML strings.
*
* @package symfony
* @subpackage yaml
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Dumper
{
/**
* Dumps a PHP value to YAML.
*
* @param mixed $input The PHP value
* @param integer $inline The level where you switch to inline YAML
* @param integer $indent The level o indentation indentation (used internally)
*
* @return string The YAML representation of the PHP value
*/
public function dump($input, $inline = 0, $indent = 0)
{
$output = '';
$prefix = $indent ? str_repeat(' ', $indent) : '';
if ($inline <= 0 || !is_array($input) || empty($input))
{
$output .= $prefix.Inline::dump($input);
}
else
{
$isAHash = array_keys($input) !== range(0, count($input) - 1);
foreach ($input as $key => $value)
{
$willBeInlined = $inline - 1 <= 0 || !is_array($value) || empty($value);
$output .= sprintf('%s%s%s%s',
$prefix,
$isAHash ? Inline::dump($key).':' : '-',
$willBeInlined ? ' ' : "\n",
$this->dump($value, $inline - 1, $willBeInlined ? 0 : $indent + 2)
).($willBeInlined ? "\n" : '');
}
}
return $output;
}
}
<?php
namespace Symfony\Component\Yaml;
/*
* This file is part of the symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Exception class used by all exceptions thrown by the component.
*
* @package symfony
* @subpackage yaml
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class ParserException extends Exception
{
}
<?php
namespace Symfony\Component\Yaml;
/*
* This file is part of the symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Exception class used by all exceptions thrown by the component.
*
* @package symfony
* @subpackage yaml
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Exception extends \Exception
{
}
<?php
namespace Symfony\Component\Yaml;
/*
* This file is part of the symfony package.
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Inline implements a YAML parser/dumper for the YAML inline syntax.
*
* @package symfony
* @subpackage yaml
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Inline
{
const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\']*(?:\'\'[^\']*)*)\')';
/**
* Convert a YAML string to a PHP array.
*
* @param string $value A YAML string
*
* @return array A PHP array representing the YAML string
*/
static public function load($value)
{
$value = trim($value);
if (0 == strlen($value))
{
return '';
}
switch ($value[0])
{
case '[':
return self::parseSequence($value);
case '{':
return self::parseMapping($value);
default:
return self::parseScalar($value);
}
}
/**
* Dumps a given PHP variable to a YAML string.
*
* @param mixed $value The PHP variable to convert
*
* @return string The YAML string representing the PHP array
*/
static public function dump($value)
{
$trueValues = '1.1' == Yaml::getSpecVersion() ? array('true', 'on', '+', 'yes', 'y') : array('true');
$falseValues = '1.1' == Yaml::getSpecVersion() ? array('false', 'off', '-', 'no', 'n') : array('false');
switch (true)
{
case is_resource($value):
throw new Exception('Unable to dump PHP resources in a YAML file.');
case is_object($value):
return '!!php/object:'.serialize($value);
case is_array($value):
return self::dumpArray($value);
case null === $value:
return 'null';
case true === $value:
return 'true';
case false === $value:
return 'false';
case ctype_digit($value):
return is_string($value) ? "'$value'" : (int) $value;
case is_numeric($value):
return is_infinite($value) ? str_ireplace('INF', '.Inf', strval($value)) : (is_string($value) ? "'$value'" : $value);
case false !== strpos($value, "\n") || false !== strpos($value, "\r"):
return sprintf('"%s"', str_replace(array('"', "\n", "\r"), array('\\"', '\n', '\r'), $value));
case preg_match('/[ \s \' " \: \{ \} \[ \] , & \* \# \?] | \A[ - ? | < > = ! % @ ` ]/x', $value):
return sprintf("'%s'", str_replace('\'', '\'\'', $value));
case '' == $value:
return "''";
case preg_match(self::getTimestampRegex(), $value):
return "'$value'";
case in_array(strtolower($value), $trueValues):
return "'$value'";
case in_array(strtolower($value), $falseValues):
return "'$value'";
case in_array(strtolower($value), array('null', '~')):
return "'$value'";
default:
return $value;
}
}
/**
* Dumps a PHP array to a YAML string.
*
* @param array $value The PHP array to dump
*
* @return string The YAML string representing the PHP array
*/
static protected function dumpArray($value)
{
// array
$keys = array_keys($value);
if (
(1 == count($keys) && '0' == $keys[0])
||
(count($keys) > 1 && array_reduce($keys, function ($v, $w) { return (integer) $v + $w; }, 0) == count($keys) * (count($keys) - 1) / 2))
{
$output = array();
foreach ($value as $val)
{
$output[] = self::dump($val);
}
return sprintf('[%s]', implode(', ', $output));
}
// mapping
$output = array();
foreach ($value as $key => $val)
{
$output[] = sprintf('%s: %s', self::dump($key), self::dump($val));
}
return sprintf('{ %s }', implode(', ', $output));
}
/**
* Parses a scalar to a YAML string.
*
* @param scalar $scalar
* @param string $delimiters
* @param array $stringDelimiter
* @param integer $i
* @param boolean $evaluate
*
* @return string A YAML string
*/
static public function parseScalar($scalar, $delimiters = null, $stringDelimiters = array('"', "'"), &$i = 0, $evaluate = true)
{
if (in_array($scalar[$i], $stringDelimiters))
{
// quoted scalar
$output = self::parseQuotedScalar($scalar, $i);
}
else
{
// "normal" string
if (!$delimiters)
{
$output = substr($scalar, $i);
$i += strlen($output);
// remove comments
if (false !== $strpos = strpos($output, ' #'))
{
$output = rtrim(substr($output, 0, $strpos));
}
}
else if (preg_match('/^(.+?)('.implode('|', $delimiters).')/', substr($scalar, $i), $match))
{
$output = $match[1];
$i += strlen($output);
}
else
{
throw new ParserException(sprintf('Malformed inline YAML string (%s).', $scalar));
}
$output = $evaluate ? self::evaluateScalar($output) : $output;
}
return $output;
}
/**
* Parses a quoted scalar to YAML.
*
* @param string $scalar
* @param integer $i
*
* @return string A YAML string
*/
static protected function parseQuotedScalar($scalar, &$i)
{
if (!preg_match('/'.self::REGEX_QUOTED_STRING.'/A', substr($scalar, $i), $match))
{
throw new ParserException(sprintf('Malformed inline YAML string (%s).', substr($scalar, $i)));
}
$output = substr($match[0], 1, strlen($match[0]) - 2);
if ('"' == $scalar[$i])
{
// evaluate the string
$output = str_replace(array('\\"', '\\n', '\\r'), array('"', "\n", "\r"), $output);
}
else
{
// unescape '
$output = str_replace('\'\'', '\'', $output);
}
$i += strlen($match[0]);
return $output;
}
/**
* Parses a sequence to a YAML string.
*
* @param string $sequence
* @param integer $i
*
* @return string A YAML string
*/
static protected function parseSequence($sequence, &$i = 0)
{
$output = array();
$len = strlen($sequence);
$i += 1;
// [foo, bar, ...]
while ($i < $len)
{
switch ($sequence[$i])
{
case '[':
// nested sequence
$output[] = self::parseSequence($sequence, $i);
break;
case '{':
// nested mapping
$output[] = self::parseMapping($sequence, $i);
break;
case ']':
return $output;
case ',':
case ' ':
break;
default:
$isQuoted = in_array($sequence[$i], array('"', "'"));
$value = self::parseScalar($sequence, array(',', ']'), array('"', "'"), $i);
if (!$isQuoted && false !== strpos($value, ': '))
{
// embedded mapping?
try
{
$value = self::parseMapping('{'.$value.'}');
}
catch (\InvalidArgumentException $e)
{
// no, it's not
}
}
$output[] = $value;
--$i;
}
++$i;
}
throw new ParserException(sprintf('Malformed inline YAML string %s', $sequence));
}
/**
* Parses a mapping to a YAML string.
*
* @param string $mapping
* @param integer $i
*
* @return string A YAML string
*/
static protected function parseMapping($mapping, &$i = 0)
{
$output = array();
$len = strlen($mapping);
$i += 1;
// {foo: bar, bar:foo, ...}
while ($i < $len)
{
switch ($mapping[$i])
{
case ' ':
case ',':
++$i;
continue 2;
case '}':
return $output;
}
// key
$key = self::parseScalar($mapping, array(':', ' '), array('"', "'"), $i, false);
// value
$done = false;
while ($i < $len)
{
switch ($mapping[$i])
{
case '[':
// nested sequence
$output[$key] = self::parseSequence($mapping, $i);
$done = true;
break;
case '{':
// nested mapping
$output[$key] = self::parseMapping($mapping, $i);
$done = true;
break;
case ':':
case ' ':
break;
default:
$output[$key] = self::parseScalar($mapping, array(',', '}'), array('"', "'"), $i);
$done = true;
--$i;
}
++$i;
if ($done)
{
continue 2;
}
}
}
throw new ParserException(sprintf('Malformed inline YAML string %s', $mapping));
}
/**
* Evaluates scalars and replaces magic values.
*
* @param string $scalar
*
* @return string A YAML string
*/
static protected function evaluateScalar($scalar)
{
$scalar = trim($scalar);
$trueValues = '1.1' == Yaml::getSpecVersion() ? array('true', 'on', '+', 'yes', 'y') : array('true');
$falseValues = '1.1' == Yaml::getSpecVersion() ? array('false', 'off', '-', 'no', 'n') : array('false');
switch (true)
{
case 'null' == strtolower($scalar):
case '' == $scalar:
case '~' == $scalar:
return null;
case 0 === strpos($scalar, '!str'):
return (string) substr($scalar, 5);
case 0 === strpos($scalar, '! '):
return intval(self::parseScalar(substr($scalar, 2)));
case 0 === strpos($scalar, '!!php/object:'):
return unserialize(substr($scalar, 13));
case ctype_digit($scalar):
$raw = $scalar;
$cast = intval($scalar);
return '0' == $scalar[0] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw);
case in_array(strtolower($scalar), $trueValues):
return true;
case in_array(strtolower($scalar), $falseValues):
return false;
case is_numeric($scalar):
return '0x' == $scalar[0].$scalar[1] ? hexdec($scalar) : floatval($scalar);
case 0 == strcasecmp($scalar, '.inf'):
case 0 == strcasecmp($scalar, '.NaN'):
return -log(0);
case 0 == strcasecmp($scalar, '-.inf'):
return log(0);
case preg_match('/^(-|\+)?[0-9,]+(\.[0-9]+)?$/', $scalar):
return floatval(str_replace(',', '', $scalar));
case preg_match(self::getTimestampRegex(), $scalar):
return strtotime($scalar);
default:
return (string) $scalar;
}
}
static protected function getTimestampRegex()
{
return <<<EOF
~^
(?P<year>[0-9][0-9][0-9][0-9])
-(?P<month>[0-9][0-9]?)
-(?P<day>[0-9][0-9]?)
(?:(?:[Tt]|[ \t]+)
(?P<hour>[0-9][0-9]?)
:(?P<minute>[0-9][0-9])
:(?P<second>[0-9][0-9])
(?:\.(?P<fraction>[0-9]*))?
(?:[ \t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?)
(?::(?P<tz_minute>[0-9][0-9]))?))?)?
$~x
EOF;
}
}
<?php
namespace Symfony\Component\Yaml;
/*
* This file is part of the symfony package.
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Parser parses YAML strings to convert them to PHP arrays.
*
* @package symfony
* @subpackage yaml
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Parser
{
protected $offset = 0;
protected $lines = array();
protected $currentLineNb = -1;
protected $currentLine = '';
protected $refs = array();
/**
* Constructor
*
* @param integer $offset The offset of YAML document (used for line numbers in error messages)
*/
public function __construct($offset = 0)
{
$this->offset = $offset;
}
/**
* Parses a YAML string to a PHP value.
*
* @param string $value A YAML string
*
* @return mixed A PHP value
*
* @throws \InvalidArgumentException If the YAML is not valid
*/
public function parse($value)
{
$this->currentLineNb = -1;
$this->currentLine = '';
$this->lines = explode("\n", $this->cleanup($value));
$data = array();
while ($this->moveToNextLine())
{
if ($this->isCurrentLineEmpty())
{
continue;
}
// tab?
if (preg_match('#^\t+#', $this->currentLine))
{
throw new ParserException(sprintf('A YAML file cannot contain tabs as indentation at line %d (%s).', $this->getRealCurrentLineNb() + 1, $this->currentLine));
}
$isRef = $isInPlace = $isProcessed = false;
if (preg_match('#^\-((?P<leadspaces>\s+)(?P<value>.+?))?\s*$#', $this->currentLine, $values))
{
if (isset($values['value']) && preg_match('#^&(?P<ref>[^ ]+) *(?P<value>.*)#', $values['value'], $matches))
{
$isRef = $matches['ref'];
$values['value'] = $matches['value'];
}
// array
if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#'))
{
$c = $this->getRealCurrentLineNb() + 1;
$parser = new Parser($c);
$parser->refs =& $this->refs;
$data[] = $parser->parse($this->getNextEmbedBlock());
}
else
{
if (isset($values['leadspaces'])
&& ' ' == $values['leadspaces']
&& preg_match('#^(?P<key>'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\{].*?) *\:(\s+(?P<value>.+?))?\s*$#', $values['value'], $matches))
{
// this is a compact notation element, add to next block and parse
$c = $this->getRealCurrentLineNb();
$parser = new Parser($c);
$parser->refs =& $this->refs;
$block = $values['value'];
if (!$this->isNextLineIndented())
{
$block .= "\n".$this->getNextEmbedBlock($this->getCurrentLineIndentation() + 2);
}
$data[] = $parser->parse($block);
}
else
{
$data[] = $this->parseValue($values['value']);
}
}
}
else if (preg_match('#^(?P<key>'.Inline::REGEX_QUOTED_STRING.'|[^ \'"].*?) *\:(\s+(?P<value>.+?))?\s*$#', $this->currentLine, $values))
{
$key = Inline::parseScalar($values['key']);
if ('<<' === $key)
{
if (isset($values['value']) && '*' === substr($values['value'], 0, 1))
{
$isInPlace = substr($values['value'], 1);
if (!array_key_exists($isInPlace, $this->refs))
{
throw new ParserException(sprintf('Reference "%s" does not exist at line %s (%s).', $isInPlace, $this->getRealCurrentLineNb() + 1, $this->currentLine));
}
}
else
{
if (isset($values['value']) && $values['value'] !== '')
{
$value = $values['value'];
}
else
{
$value = $this->getNextEmbedBlock();
}
$c = $this->getRealCurrentLineNb() + 1;
$parser = new Parser($c);
$parser->refs =& $this->refs;
$parsed = $parser->parse($value);
$merged = array();
if (!is_array($parsed))
{
throw new ParserException(sprintf("YAML merge keys used with a scalar value instead of an array at line %s (%s)", $this->getRealCurrentLineNb() + 1, $this->currentLine));
}
else if (isset($parsed[0]))
{
// Numeric array, merge individual elements
foreach (array_reverse($parsed) as $parsedItem)
{
if (!is_array($parsedItem))
{
throw new ParserException(sprintf("Merge items must be arrays at line %s (%s).", $this->getRealCurrentLineNb() + 1, $parsedItem));
}
$merged = array_merge($parsedItem, $merged);
}
}
else
{
// Associative array, merge
$merged = array_merge($merge, $parsed);
}
$isProcessed = $merged;
}
}
else if (isset($values['value']) && preg_match('#^&(?P<ref>[^ ]+) *(?P<value>.*)#', $values['value'], $matches))
{
$isRef = $matches['ref'];
$values['value'] = $matches['value'];
}
if ($isProcessed)
{
// Merge keys
$data = $isProcessed;
}
// hash
else if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#'))
{
// if next line is less indented or equal, then it means that the current value is null
if ($this->isNextLineIndented())
{
$data[$key] = null;
}
else
{
$c = $this->getRealCurrentLineNb() + 1;
$parser = new Parser($c);
$parser->refs =& $this->refs;
$data[$key] = $parser->parse($this->getNextEmbedBlock());
}
}
else
{
if ($isInPlace)
{
$data = $this->refs[$isInPlace];
}
else
{
$data[$key] = $this->parseValue($values['value']);
}
}
}
else
{
// 1-liner followed by newline
if (2 == count($this->lines) && empty($this->lines[1]))
{
$value = Inline::load($this->lines[0]);
if (is_array($value))
{
$first = reset($value);
if ('*' === substr($first, 0, 1))
{
$data = array();
foreach ($value as $alias)
{
$data[] = $this->refs[substr($alias, 1)];
}
$value = $data;
}
}
return $value;
}
switch (preg_last_error())
{
case PREG_INTERNAL_ERROR:
$error = 'Internal PCRE error on line';
break;
case PREG_BACKTRACK_LIMIT_ERROR:
$error = 'pcre.backtrack_limit reached on line';
break;
case PREG_RECURSION_LIMIT_ERROR:
$error = 'pcre.recursion_limit reached on line';
break;
case PREG_BAD_UTF8_ERROR:
$error = 'Malformed UTF-8 data on line';
break;
case PREG_BAD_UTF8_OFFSET_ERROR:
$error = 'Offset doesn\'t correspond to the begin of a valid UTF-8 code point on line';
break;
default:
$error = 'Unable to parse line';
}
throw new ParserException(sprintf('%s %d (%s).', $error, $this->getRealCurrentLineNb() + 1, $this->currentLine));
}
if ($isRef)
{
$this->refs[$isRef] = end($data);
}
}
return empty($data) ? null : $data;
}
/**
* Returns the current line number (takes the offset into account).
*
* @return integer The current line number
*/
protected function getRealCurrentLineNb()
{
return $this->currentLineNb + $this->offset;
}
/**
* Returns the current line indentation.
*
* @return integer The current line indentation
*/
protected function getCurrentLineIndentation()
{
return strlen($this->currentLine) - strlen(ltrim($this->currentLine, ' '));
}
/**
* Returns the next embed block of YAML.
*
* @param integer $indentation The indent level at which the block is to be read, or null for default
*
* @return string A YAML string
*/
protected function getNextEmbedBlock($indentation = null)
{
$this->moveToNextLine();
if (null === $indentation)
{
$newIndent = $this->getCurrentLineIndentation();
if (!$this->isCurrentLineEmpty() && 0 == $newIndent)
{
throw new ParserException(sprintf('Indentation problem at line %d (%s)', $this->getRealCurrentLineNb() + 1, $this->currentLine));
}
}
else
{
$newIndent = $indentation;
}
$data = array(substr($this->currentLine, $newIndent));
while ($this->moveToNextLine())
{
if ($this->isCurrentLineEmpty())
{
if ($this->isCurrentLineBlank())
{
$data[] = substr($this->currentLine, $newIndent);
}
continue;
}
$indent = $this->getCurrentLineIndentation();
if (preg_match('#^(?P<text> *)$#', $this->currentLine, $match))
{
// empty line
$data[] = $match['text'];
}
else if ($indent >= $newIndent)
{
$data[] = substr($this->currentLine, $newIndent);
}
else if (0 == $indent)
{
$this->moveToPreviousLine();
break;
}
else
{
throw new ParserException(sprintf('Indentation problem at line %d (%s)', $this->getRealCurrentLineNb() + 1, $this->currentLine));
}
}
return implode("\n", $data);
}
/**
* Moves the parser to the next line.
*/
protected function moveToNextLine()
{
if ($this->currentLineNb >= count($this->lines) - 1)
{
return false;
}
$this->currentLine = $this->lines[++$this->currentLineNb];
return true;
}
/**
* Moves the parser to the previous line.
*/
protected function moveToPreviousLine()
{
$this->currentLine = $this->lines[--$this->currentLineNb];
}
/**
* Parses a YAML value.
*
* @param string $value A YAML value
*
* @return mixed A PHP value
*/
protected function parseValue($value)
{
if ('*' === substr($value, 0, 1))
{
if (false !== $pos = strpos($value, '#'))
{
$value = substr($value, 1, $pos - 2);
}
else
{
$value = substr($value, 1);
}
if (!array_key_exists($value, $this->refs))
{
throw new ParserException(sprintf('Reference "%s" does not exist (%s).', $value, $this->currentLine));
}
return $this->refs[$value];
}
if (preg_match('/^(?P<separator>\||>)(?P<modifiers>\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P<comments> +#.*)?$/', $value, $matches))
{
$modifiers = isset($matches['modifiers']) ? $matches['modifiers'] : '';
return $this->parseFoldedScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), intval(abs($modifiers)));
}
else
{
return Inline::load($value);
}
}
/**
* Parses a folded scalar.
*
* @param string $separator The separator that was used to begin this folded scalar (| or >)
* @param string $indicator The indicator that was used to begin this folded scalar (+ or -)
* @param integer $indentation The indentation that was used to begin this folded scalar
*
* @return string The text value
*/
protected function parseFoldedScalar($separator, $indicator = '', $indentation = 0)
{
$separator = '|' == $separator ? "\n" : ' ';
$text = '';
$notEOF = $this->moveToNextLine();
while ($notEOF && $this->isCurrentLineBlank())
{
$text .= "\n";
$notEOF = $this->moveToNextLine();
}
if (!$notEOF)
{
return '';
}
if (!preg_match('#^(?P<indent>'.($indentation ? str_repeat(' ', $indentation) : ' +').')(?P<text>.*)$#', $this->currentLine, $matches))
{
$this->moveToPreviousLine();
return '';
}
$textIndent = $matches['indent'];
$previousIndent = 0;
$text .= $matches['text'].$separator;
while ($this->currentLineNb + 1 < count($this->lines))
{
$this->moveToNextLine();
if (preg_match('#^(?P<indent> {'.strlen($textIndent).',})(?P<text>.+)$#', $this->currentLine, $matches))
{
if (' ' == $separator && $previousIndent != $matches['indent'])
{
$text = substr($text, 0, -1)."\n";
}
$previousIndent = $matches['indent'];
$text .= str_repeat(' ', $diff = strlen($matches['indent']) - strlen($textIndent)).$matches['text'].($diff ? "\n" : $separator);
}
else if (preg_match('#^(?P<text> *)$#', $this->currentLine, $matches))
{
$text .= preg_replace('#^ {1,'.strlen($textIndent).'}#', '', $matches['text'])."\n";
}
else
{
$this->moveToPreviousLine();
break;
}
}
if (' ' == $separator)
{
// replace last separator by a newline
$text = preg_replace('/ (\n*)$/', "\n$1", $text);
}
switch ($indicator)
{
case '':
$text = preg_replace('#\n+$#s', "\n", $text);
break;
case '+':
break;
case '-':
$text = preg_replace('#\n+$#s', '', $text);
break;
}
return $text;
}
/**
* Returns true if the next line is indented.
*
* @return Boolean Returns true if the next line is indented, false otherwise
*/
protected function isNextLineIndented()
{
$currentIndentation = $this->getCurrentLineIndentation();
$notEOF = $this->moveToNextLine();
while ($notEOF && $this->isCurrentLineEmpty())
{
$notEOF = $this->moveToNextLine();
}
if (false === $notEOF)
{
return false;
}
$ret = false;
if ($this->getCurrentLineIndentation() <= $currentIndentation)
{
$ret = true;
}
$this->moveToPreviousLine();
return $ret;
}
/**
* Returns true if the current line is blank or if it is a comment line.
*
* @return Boolean Returns true if the current line is empty or if it is a comment line, false otherwise
*/
protected function isCurrentLineEmpty()
{
return $this->isCurrentLineBlank() || $this->isCurrentLineComment();
}
/**
* Returns true if the current line is blank.
*
* @return Boolean Returns true if the current line is blank, false otherwise
*/
protected function isCurrentLineBlank()
{
return '' == trim($this->currentLine, ' ');
}
/**
* Returns true if the current line is a comment line.
*
* @return Boolean Returns true if the current line is a comment line, false otherwise
*/
protected function isCurrentLineComment()
{
//checking explicitly the first char of the trim is faster than loops or strpos
$ltrimmedLine = ltrim($this->currentLine, ' ');
return $ltrimmedLine[0] === '#';
}
/**
* Cleanups a YAML string to be parsed.
*
* @param string $value The input YAML string
*
* @return string A cleaned up YAML string
*/
protected function cleanup($value)
{
$value = str_replace(array("\r\n", "\r"), "\n", $value);
if (!preg_match("#\n$#", $value))
{
$value .= "\n";
}
// strip YAML header
$count = 0;
$value = preg_replace('#^\%YAML[: ][\d\.]+.*\n#s', '', $value, -1, $count);
$this->offset += $count;
// remove leading comments and/or ---
$trimmedValue = preg_replace('#^((\#.*?\n)|(\-\-\-.*?\n))*#s', '', $value, -1, $count);
if ($count == 1)
{
// items have been removed, update the offset
$this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n");
$value = $trimmedValue;
}
return $value;
}
}
<?php
namespace Symfony\Component\Console\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\Output;
use Symfony\Component\Console\Command\Command;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* ListCommand displays the list of all available commands for the application.
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class ListCommand extends Command
{
/**
* @see Command
*/
protected function configure()
{
$this
->setDefinition(array(
new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
new InputOption('xml', null, InputOption::PARAMETER_NONE, 'To output help as XML'),
))
->setName('list')
->setDescription('Lists commands')
->setHelp(<<<EOF
The <info>list</info> command lists all commands:
<info>./symfony list</info>
You can also display the commands for a specific namespace:
<info>./symfony list test</info>
You can also output the information as XML by using the <comment>--xml</comment> option:
<info>./symfony list --xml</info>
EOF
);
}
/**
* @see Command
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
if ($input->getOption('xml')) {
$output->writeln($this->application->asXml($input->getArgument('namespace')), Output::OUTPUT_RAW);
} else {
$output->writeln($this->application->asText($input->getArgument('namespace')));
}
}
}
<?php
namespace Symfony\Component\Console\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\Output;
use Symfony\Component\Console\Command\Command;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* HelpCommand displays the help for a given command.
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class HelpCommand extends Command
{
protected $command;
/**
* @see Command
*/
protected function configure()
{
$this->ignoreValidationErrors = true;
$this
->setDefinition(array(
new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
new InputOption('xml', null, InputOption::PARAMETER_NONE, 'To output help as XML'),
))
->setName('help')
->setAliases(array('?'))
->setDescription('Displays help for a command')
->setHelp(<<<EOF
The <info>help</info> command displays help for a given command:
<info>./symfony help list</info>
You can also output the help as XML by using the <comment>--xml</comment> option:
<info>./symfony help --xml list</info>
EOF
);
}
public function setCommand(Command $command)
{
$this->command = $command;
}
/**
* @see Command
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
if (null === $this->command) {
$this->command = $this->application->getCommand($input->getArgument('command_name'));
}
if ($input->getOption('xml')) {
$output->writeln($this->command->asXml(), Output::OUTPUT_RAW);
} else {
$output->writeln($this->command->asText());
}
}
}
<?php
namespace Symfony\Component\Console\Command;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Application;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* Base class for all commands.
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Command
{
protected $name;
protected $namespace;
protected $aliases;
protected $definition;
protected $help;
protected $application;
protected $description;
protected $ignoreValidationErrors;
protected $applicationDefinitionMerged;
protected $code;
/**
* Constructor.
*
* @param string $name The name of the command
*
* @throws \LogicException When the command name is empty
*/
public function __construct($name = null)
{
$this->definition = new InputDefinition();
$this->ignoreValidationErrors = false;
$this->applicationDefinitionMerged = false;
$this->aliases = array();
if (null !== $name) {
$this->setName($name);
}
$this->configure();
if (!$this->name) {
throw new \LogicException('The command name cannot be empty.');
}
}
/**
* Sets the application instance for this command.
*
* @param Application $application An Application instance
*/
public function setApplication(Application $application = null)
{
$this->application = $application;
}
/**
* Configures the current command.
*/
protected function configure()
{
}
/**
* Executes the current command.
*
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
*
* @return integer 0 if everything went fine, or an error code
*
* @throws \LogicException When this abstract class is not implemented
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
throw new \LogicException('You must override the execute() method in the concrete command class.');
}
/**
* Interacts with the user.
*
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
*/
protected function interact(InputInterface $input, OutputInterface $output)
{
}
/**
* Initializes the command just after the input has been validated.
*
* This is mainly useful when a lot of commands extends one main command
* where some things need to be initialized based on the input arguments and options.
*
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
*/
protected function initialize(InputInterface $input, OutputInterface $output)
{
}
/**
* Runs the command.
*
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
*/
public function run(InputInterface $input, OutputInterface $output)
{
// add the application arguments and options
$this->mergeApplicationDefinition();
// bind the input against the command specific arguments/options
try {
$input->bind($this->definition);
} catch (\Exception $e) {
if (!$this->ignoreValidationErrors) {
throw $e;
}
}
$this->initialize($input, $output);
if ($input->isInteractive()) {
$this->interact($input, $output);
}
$input->validate();
if ($this->code) {
return call_user_func($this->code, $input, $output);
} else {
return $this->execute($input, $output);
}
}
/**
* Sets the code to execute when running this command.
*
* @param \Closure $code A \Closure
*
* @return Command The current instance
*/
public function setCode(\Closure $code)
{
$this->code = $code;
return $this;
}
/**
* Merges the application definition with the command definition.
*/
protected function mergeApplicationDefinition()
{
if (null === $this->application || true === $this->applicationDefinitionMerged) {
return;
}
$this->definition->setArguments(array_merge(
$this->application->getDefinition()->getArguments(),
$this->definition->getArguments()
));
$this->definition->addOptions($this->application->getDefinition()->getOptions());
$this->applicationDefinitionMerged = true;
}
/**
* Sets an array of argument and option instances.
*
* @param array|Definition $definition An array of argument and option instances or a definition instance
*
* @return Command The current instance
*/
public function setDefinition($definition)
{
if ($definition instanceof InputDefinition) {
$this->definition = $definition;
} else {
$this->definition->setDefinition($definition);
}
$this->applicationDefinitionMerged = false;
return $this;
}
/**
* Gets the InputDefinition attached to this Command.
*
* @return InputDefinition An InputDefinition instance
*/
public function getDefinition()
{
return $this->definition;
}
/**
* Adds an argument.
*
* @param string $name The argument name
* @param integer $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL
* @param string $description A description text
* @param mixed $default The default value (for InputArgument::OPTIONAL mode only)
*
* @return Command The current instance
*/
public function addArgument($name, $mode = null, $description = '', $default = null)
{
$this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
return $this;
}
/**
* Adds an option.
*
* @param string $name The option name
* @param string $shortcut The shortcut (can be null)
* @param integer $mode The option mode: self::PARAMETER_REQUIRED, self::PARAMETER_NONE or self::PARAMETER_OPTIONAL
* @param string $description A description text
* @param mixed $default The default value (must be null for self::PARAMETER_REQUIRED or self::PARAMETER_NONE)
*
* @return Command The current instance
*/
public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
{
$this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
return $this;
}
/**
* Sets the name of the command.
*
* This method can set both the namespace and the name if
* you separate them by a colon (:)
*
* $command->setName('foo:bar');
*
* @param string $name The command name
*
* @return Command The current instance
*
* @throws \InvalidArgumentException When command name given is empty
*/
public function setName($name)
{
if (false !== $pos = strrpos($name, ':')) {
$namespace = substr($name, 0, $pos);
$name = substr($name, $pos + 1);
} else {
$namespace = $this->namespace;
}
if (!$name) {
throw new \InvalidArgumentException('A command name cannot be empty.');
}
$this->namespace = $namespace;
$this->name = $name;
return $this;
}
/**
* Returns the command namespace.
*
* @return string The command namespace
*/
public function getNamespace()
{
return $this->namespace;
}
/**
* Returns the command name
*
* @return string The command name
*/
public function getName()
{
return $this->name;
}
/**
* Returns the fully qualified command name.
*
* @return string The fully qualified command name
*/
public function getFullName()
{
return $this->getNamespace() ? $this->getNamespace().':'.$this->getName() : $this->getName();
}
/**
* Sets the description for the command.
*
* @param string $description The description for the command
*
* @return Command The current instance
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Returns the description for the command.
*
* @return string The description for the command
*/
public function getDescription()
{
return $this->description;
}
/**
* Sets the help for the command.
*
* @param string $help The help for the command
*
* @return Command The current instance
*/
public function setHelp($help)
{
$this->help = $help;
return $this;
}
/**
* Returns the help for the command.
*
* @return string The help for the command
*/
public function getHelp()
{
return $this->help;
}
/**
* Returns the processed help for the command replacing the %command.name% and
* %command.full_name% patterns with the real values dynamically.
*
* @return string The processed help for the command
*/
public function getProcessedHelp()
{
$name = $this->namespace.':'.$this->name;
$placeholders = array(
'%command.name%',
'%command.full_name%'
);
$replacements = array(
$name,
$_SERVER['PHP_SELF'].' '.$name
);
return str_replace($placeholders, $replacements, $this->getHelp());
}
/**
* Sets the aliases for the command.
*
* @param array $aliases An array of aliases for the command
*
* @return Command The current instance
*/
public function setAliases($aliases)
{
$this->aliases = $aliases;
return $this;
}
/**
* Returns the aliases for the command.
*
* @return array An array of aliases for the command
*/
public function getAliases()
{
return $this->aliases;
}
/**
* Returns the synopsis for the command.
*
* @return string The synopsis
*/
public function getSynopsis()
{
return sprintf('%s %s', $this->getFullName(), $this->definition->getSynopsis());
}
/**
* Gets a helper instance by name.
*
* @param string $name The helper name
*
* @return mixed The helper value
*
* @throws \InvalidArgumentException if the helper is not defined
*/
protected function getHelper($name)
{
return $this->application->getHelperSet()->get($name);
}
/**
* Gets a helper instance by name.
*
* @param string $name The helper name
*
* @return mixed The helper value
*
* @throws \InvalidArgumentException if the helper is not defined
*/
public function __get($name)
{
return $this->application->getHelperSet()->get($name);
}
/**
* Returns a text representation of the command.
*
* @return string A string representing the command
*/
public function asText()
{
$messages = array(
'<comment>Usage:</comment>',
' '.$this->getSynopsis(),
'',
);
if ($this->getAliases()) {
$messages[] = '<comment>Aliases:</comment> <info>'.implode(', ', $this->getAliases()).'</info>';
}
$messages[] = $this->definition->asText();
if ($help = $this->getProcessedHelp()) {
$messages[] = '<comment>Help:</comment>';
$messages[] = ' '.implode("\n ", explode("\n", $help))."\n";
}
return implode("\n", $messages);
}
/**
* Returns an XML representation of the command.
*
* @param Boolean $asDom Whether to return a DOM or an XML string
*
* @return string|DOMDocument An XML string representing the command
*/
public function asXml($asDom = false)
{
$dom = new \DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;
$dom->appendChild($commandXML = $dom->createElement('command'));
$commandXML->setAttribute('id', $this->getFullName());
$commandXML->setAttribute('namespace', $this->getNamespace() ? $this->getNamespace() : '_global');
$commandXML->setAttribute('name', $this->getName());
$commandXML->appendChild($usageXML = $dom->createElement('usage'));
$usageXML->appendChild($dom->createTextNode(sprintf($this->getSynopsis(), '')));
$commandXML->appendChild($descriptionXML = $dom->createElement('description'));
$descriptionXML->appendChild($dom->createTextNode(implode("\n ", explode("\n", $this->getDescription()))));
$commandXML->appendChild($helpXML = $dom->createElement('help'));
$help = $this->help;
$helpXML->appendChild($dom->createTextNode(implode("\n ", explode("\n", $help))));
$commandXML->appendChild($aliasesXML = $dom->createElement('aliases'));
foreach ($this->getAliases() as $alias) {
$aliasesXML->appendChild($aliasXML = $dom->createElement('alias'));
$aliasXML->appendChild($dom->createTextNode($alias));
}
$definition = $this->definition->asXml(true);
$commandXML->appendChild($dom->importNode($definition->getElementsByTagName('arguments')->item(0), true));
$commandXML->appendChild($dom->importNode($definition->getElementsByTagName('options')->item(0), true));
return $asDom ? $dom : $dom->saveXml();
}
}
<?php
namespace Symfony\Component\Console\Output;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* ConsoleOutput is the default class for all CLI output. It uses STDOUT.
*
* This class is a convenient wrapper around `StreamOutput`.
*
* $output = new ConsoleOutput();
*
* This is equivalent to:
*
* $output = new StreamOutput(fopen('php://stdout', 'w'));
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class ConsoleOutput extends StreamOutput
{
/**
* Constructor.
*
* @param integer $verbosity The verbosity level (self::VERBOSITY_QUIET, self::VERBOSITY_NORMAL, self::VERBOSITY_VERBOSE)
* @param Boolean $decorated Whether to decorate messages or not (null for auto-guessing)
*/
public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null)
{
parent::__construct(fopen('php://stdout', 'w'), $verbosity, $decorated);
}
}
<?php
namespace Symfony\Component\Console\Output;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* OutputInterface is the interface implemented by all Output classes.
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
interface OutputInterface
{
/**
* Writes a message to the output.
*
* @param string|array $messages The message as an array of lines of a single string
* @param Boolean $newline Whether to add a newline or not
* @param integer $type The type of output
*
* @throws \InvalidArgumentException When unknown output type is given
*/
function write($messages, $newline = false, $type = 0);
/**
* Sets the verbosity of the output.
*
* @param integer $level The level of verbosity
*/
function setVerbosity($level);
/**
* Sets the decorated flag.
*
* @param Boolean $decorated Whether to decorated the messages or not
*/
function setDecorated($decorated);
}
<?php
namespace Symfony\Component\Console\Output;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* StreamOutput writes the output to a given stream.
*
* Usage:
*
* $output = new StreamOutput(fopen('php://stdout', 'w'));
*
* As `StreamOutput` can use any stream, you can also use a file:
*
* $output = new StreamOutput(fopen('/path/to/output.log', 'a', false));
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class StreamOutput extends Output
{
protected $stream;
/**
* Constructor.
*
* @param mixed $stream A stream resource
* @param integer $verbosity The verbosity level (self::VERBOSITY_QUIET, self::VERBOSITY_NORMAL, self::VERBOSITY_VERBOSE)
* @param Boolean $decorated Whether to decorate messages or not (null for auto-guessing)
*
* @throws \InvalidArgumentException When first argument is not a real stream
*/
public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null)
{
if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) {
throw new \InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
}
$this->stream = $stream;
if (null === $decorated) {
$decorated = $this->hasColorSupport($decorated);
}
parent::__construct($verbosity, $decorated);
}
/**
* Gets the stream attached to this StreamOutput instance.
*
* @return resource A stream resource
*/
public function getStream()
{
return $this->stream;
}
/**
* Writes a message to the output.
*
* @param string $message A message to write to the output
* @param Boolean $newline Whether to add a newline or not
*
* @throws \RuntimeException When unable to write output (should never happen)
*/
public function doWrite($message, $newline)
{
if (false === @fwrite($this->stream, $message.($newline ? PHP_EOL : ''))) {
// @codeCoverageIgnoreStart
// should never happen
throw new \RuntimeException('Unable to write output.');
// @codeCoverageIgnoreEnd
}
flush();
}
/**
* Returns true if the stream supports colorization.
*
* Colorization is disabled if not supported by the stream:
*
* - windows without ansicon
* - non tty consoles
*
* @return Boolean true if the stream supports colorization, false otherwise
*/
protected function hasColorSupport()
{
// @codeCoverageIgnoreStart
if (DIRECTORY_SEPARATOR == '\\') {
return false !== getenv('ANSICON');
} else {
return function_exists('posix_isatty') && @posix_isatty($this->stream);
}
// @codeCoverageIgnoreEnd
}
}
<?php
namespace Symfony\Component\Console\Output;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* Base class for output classes.
*
* There is three level of verbosity:
*
* * normal: no option passed (normal output - information)
* * verbose: -v (more output - debug)
* * quiet: -q (no output)
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
abstract class Output implements OutputInterface
{
const VERBOSITY_QUIET = 0;
const VERBOSITY_NORMAL = 1;
const VERBOSITY_VERBOSE = 2;
const OUTPUT_NORMAL = 0;
const OUTPUT_RAW = 1;
const OUTPUT_PLAIN = 2;
protected $verbosity;
protected $decorated;
static protected $styles = array(
'error' => array('bg' => 'red', 'fg' => 'white'),
'info' => array('fg' => 'green'),
'comment' => array('fg' => 'yellow'),
'question' => array('bg' => 'cyan', 'fg' => 'black'),
);
static protected $options = array('bold' => 1, 'underscore' => 4, 'blink' => 5, 'reverse' => 7, 'conceal' => 8);
static protected $foreground = array('black' => 30, 'red' => 31, 'green' => 32, 'yellow' => 33, 'blue' => 34, 'magenta' => 35, 'cyan' => 36, 'white' => 37);
static protected $background = array('black' => 40, 'red' => 41, 'green' => 42, 'yellow' => 43, 'blue' => 44, 'magenta' => 45, 'cyan' => 46, 'white' => 47);
/**
* Constructor.
*
* @param integer $verbosity The verbosity level (self::VERBOSITY_QUIET, self::VERBOSITY_NORMAL, self::VERBOSITY_VERBOSE)
* @param Boolean $decorated Whether to decorate messages or not (null for auto-guessing)
*/
public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null)
{
$this->decorated = (Boolean) $decorated;
$this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity;
}
/**
* Sets a new style.
*
* @param string $name The style name
* @param array $options An array of options
*/
static public function setStyle($name, $options = array())
{
static::$styles[strtolower($name)] = $options;
}
/**
* Sets the decorated flag.
*
* @param Boolean $decorated Whether to decorated the messages or not
*/
public function setDecorated($decorated)
{
$this->decorated = (Boolean) $decorated;
}
/**
* Gets the decorated flag.
*
* @return Boolean true if the output will decorate messages, false otherwise
*/
public function isDecorated()
{
return $this->decorated;
}
/**
* Sets the verbosity of the output.
*
* @param integer $level The level of verbosity
*/
public function setVerbosity($level)
{
$this->verbosity = (int) $level;
}
/**
* Gets the current verbosity of the output.
*
* @return integer The current level of verbosity
*/
public function getVerbosity()
{
return $this->verbosity;
}
/**
* Writes a message to the output and adds a newline at the end.
*
* @param string|array $messages The message as an array of lines of a single string
* @param integer $type The type of output
*/
public function writeln($messages, $type = 0)
{
$this->write($messages, true, $type);
}
/**
* Writes a message to the output.
*
* @param string|array $messages The message as an array of lines of a single string
* @param Boolean $newline Whether to add a newline or not
* @param integer $type The type of output
*
* @throws \InvalidArgumentException When unknown output type is given
*/
public function write($messages, $newline = false, $type = 0)
{
if (self::VERBOSITY_QUIET === $this->verbosity) {
return;
}
if (!is_array($messages)) {
$messages = array($messages);
}
foreach ($messages as $message) {
switch ($type) {
case Output::OUTPUT_NORMAL:
$message = $this->format($message);
break;
case Output::OUTPUT_RAW:
break;
case Output::OUTPUT_PLAIN:
$message = strip_tags($this->format($message));
break;
default:
throw new \InvalidArgumentException(sprintf('Unknown output type given (%s)', $type));
}
$this->doWrite($message, $newline);
}
}
/**
* Writes a message to the output.
*
* @param string $message A message to write to the output
* @param Boolean $newline Whether to add a newline or not
*/
abstract public function doWrite($message, $newline);
/**
* Formats a message according to the given styles.
*
* @param string $message The message to style
*
* @return string The styled message
*/
protected function format($message)
{
$message = preg_replace_callback('#<([a-z][a-z0-9\-_=;]+)>#i', array($this, 'replaceStartStyle'), $message);
return preg_replace_callback('#</([a-z][a-z0-9\-_]*)?>#i', array($this, 'replaceEndStyle'), $message);
}
/**
* @throws \InvalidArgumentException When style is unknown
*/
protected function replaceStartStyle($match)
{
if (!$this->decorated) {
return '';
}
if (isset(static::$styles[strtolower($match[1])])) {
$parameters = static::$styles[strtolower($match[1])];
} else {
// bg=blue;fg=red
if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($match[1]), $matches, PREG_SET_ORDER)) {
throw new \InvalidArgumentException(sprintf('Unknown style "%s".', $match[1]));
}
$parameters = array();
foreach ($matches as $match) {
$parameters[$match[1]] = $match[2];
}
}
$codes = array();
if (isset($parameters['fg'])) {
$codes[] = static::$foreground[$parameters['fg']];
}
if (isset($parameters['bg'])) {
$codes[] = static::$background[$parameters['bg']];
}
foreach (static::$options as $option => $value) {
if (isset($parameters[$option]) && $parameters[$option]) {
$codes[] = $value;
}
}
return "\033[".implode(';', $codes).'m';
}
protected function replaceEndStyle($match)
{
if (!$this->decorated) {
return '';
}
return "\033[0m";
}
}
<?php
namespace Symfony\Component\Console\Output;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* NullOutput suppresses all output.
*
* $output = new NullOutput();
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class NullOutput extends Output
{
/**
* Writes a message to the output.
*
* @param string $message A message to write to the output
* @param Boolean $newline Whether to add a newline or not
*/
public function doWrite($message, $newline)
{
}
}
<?php
namespace Symfony\Component\Console;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Input\StringInput;
use Symfony\Component\Console\Output\ConsoleOutput;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* A Shell wraps an Application to add shell capabilities to it.
*
* This class only works with a PHP compiled with readline support
* (either --with-readline or --with-libedit)
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Shell
{
protected $application;
protected $history;
protected $output;
/**
* Constructor.
*
* If there is no readline support for the current PHP executable
* a \RuntimeException exception is thrown.
*
* @param Application $application An application instance
*
* @throws \RuntimeException When Readline extension is not enabled
*/
public function __construct(Application $application)
{
if (!function_exists('readline')) {
throw new \RuntimeException('Unable to start the shell as the Readline extension is not enabled.');
}
$this->application = $application;
$this->history = getenv('HOME').'/.history_'.$application->getName();
$this->output = new ConsoleOutput();
}
/**
* Runs the shell.
*/
public function run()
{
$this->application->setAutoExit(false);
$this->application->setCatchExceptions(true);
readline_read_history($this->history);
readline_completion_function(array($this, 'autocompleter'));
$this->output->writeln($this->getHeader());
while (true) {
$command = readline($this->application->getName().' > ');
if (false === $command) {
$this->output->writeln("\n");
break;
}
readline_add_history($command);
readline_write_history($this->history);
if (0 !== $ret = $this->application->run(new StringInput($command), $this->output)) {
$this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret));
}
}
}
/**
* Tries to return autocompletion for the current entered text.
*
* @param string $text The last segment of the entered text
* @param integer $position The current position
*/
protected function autocompleter($text, $position)
{
$info = readline_info();
$text = substr($info['line_buffer'], 0, $info['end']);
if ($info['point'] !== $info['end']) {
return true;
}
// task name?
if (false === strpos($text, ' ') || !$text) {
return array_keys($this->application->getCommands());
}
// options and arguments?
try {
$command = $this->application->findCommand(substr($text, 0, strpos($text, ' ')));
} catch (\Exception $e) {
return true;
}
$list = array('--help');
foreach ($command->getDefinition()->getOptions() as $option) {
$list[] = '--'.$option->getName();
}
return $list;
}
/**
* Returns the shell header.
*
* @return string The header string
*/
protected function getHeader()
{
return <<<EOF
Welcome to the <info>{$this->application->getName()}</info> shell (<comment>{$this->application->getVersion()}</comment>).
At the prompt, type <comment>help</comment> for some help,
or <comment>list</comment> to get a list available commands.
To exit the shell, type <comment>^D</comment>.
EOF;
}
}
<?php
namespace Symfony\Component\Console\Helper;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* The Formatter class provides helpers to format messages.
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class FormatterHelper extends Helper
{
/**
* Formats a message within a section.
*
* @param string $section The section name
* @param string $message The message
* @param string $style The style to apply to the section
*/
public function formatSection($section, $message, $style = 'info')
{
return sprintf('<%s>[%s]</%s> %s', $style, $section, $style, $message);
}
/**
* Formats a message as a block of text.
*
* @param string|array $messages The message to write in the block
* @param string $style The style to apply to the whole block
* @param Boolean $large Whether to return a large block
*
* @return string The formatter message
*/
public function formatBlock($messages, $style, $large = false)
{
if (!is_array($messages)) {
$messages = array($messages);
}
$len = 0;
$lines = array();
foreach ($messages as $message) {
$lines[] = sprintf($large ? ' %s ' : ' %s ', $message);
$len = max($this->strlen($message) + ($large ? 4 : 2), $len);
}
$messages = $large ? array(str_repeat(' ', $len)) : array();
foreach ($lines as $line) {
$messages[] = $line.str_repeat(' ', $len - $this->strlen($line));
}
if ($large) {
$messages[] = str_repeat(' ', $len);
}
foreach ($messages as &$message) {
$message = sprintf('<%s>%s</%s>', $style, $message, $style);
}
return implode("\n", $messages);
}
protected function strlen($string)
{
return function_exists('mb_strlen') ? mb_strlen($string) : strlen($string);
}
/**
* Returns the helper's canonical name
*/
public function getName()
{
return 'formatter';
}
}
<?php
namespace Symfony\Component\Console\Helper;
use Symfony\Component\Console\Command\Command;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* HelperSet represents a set of helpers to be used with a command.
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class HelperSet
{
protected $helpers;
protected $command;
/**
* @param Helper[] $helpers An array of helper.
*/
public function __construct(array $helpers = array())
{
$this->helpers = array();
foreach ($helpers as $alias => $helper) {
$this->set($helper, is_int($alias) ? null : $alias);
}
}
/**
* Sets a helper.
*
* @param HelperInterface $value The helper instance
* @param string $alias An alias
*/
public function set(HelperInterface $helper, $alias = null)
{
$this->helpers[$helper->getName()] = $helper;
if (null !== $alias) {
$this->helpers[$alias] = $helper;
}
$helper->setHelperSet($this);
}
/**
* Returns true if the helper if defined.
*
* @param string $name The helper name
*
* @return Boolean true if the helper is defined, false otherwise
*/
public function has($name)
{
return isset($this->helpers[$name]);
}
/**
* Gets a helper value.
*
* @param string $name The helper name
*
* @return HelperInterface The helper instance
*
* @throws \InvalidArgumentException if the helper is not defined
*/
public function get($name)
{
if (!$this->has($name)) {
throw new \InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name));
}
return $this->helpers[$name];
}
/**
* Sets the command associated with this helper set.
*
* @param Command $command A Command instance
*/
public function setCommand(Command $command = null)
{
$this->command = $command;
}
/**
* Gets the command associated with this helper set.
*
* @return Command A Command instance
*/
public function getCommand()
{
return $this->command;
}
}
<?php
namespace Symfony\Component\Console\Helper;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* Helper is the base class for all helper classes.
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
abstract class Helper implements HelperInterface
{
protected $helperSet = null;
/**
* Sets the helper set associated with this helper.
*
* @param HelperSet $helperSet A HelperSet instance
*/
public function setHelperSet(HelperSet $helperSet = null)
{
$this->helperSet = $helperSet;
}
/**
* Gets the helper set associated with this helper.
*
* @return HelperSet A HelperSet instance
*/
public function getHelperSet()
{
return $this->helperSet;
}
}
<?php
namespace Symfony\Component\Console\Helper;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* HelperInterface is the interface all helpers must implement.
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
interface HelperInterface
{
/**
* Sets the helper set associated with this helper.
*
* @param HelperSet $helperSet A HelperSet instance
*/
function setHelperSet(HelperSet $helperSet = null);
/**
* Gets the helper set associated with this helper.
*
* @return HelperSet A HelperSet instance
*/
function getHelperSet();
/**
* Returns the canonical name of this helper.
*
* @return string The canonical name
*/
function getName();
}
<?php
namespace Symfony\Component\Console\Helper;
use Symfony\Component\Console\Output\OutputInterface;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* The Dialog class provides helpers to interact with the user.
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class DialogHelper extends Helper
{
/**
* Asks a question to the user.
*
* @param OutputInterface $output
* @param string|array $question The question to ask
* @param string $default The default answer if none is given by the user
*
* @return string The user answer
*/
public function ask(OutputInterface $output, $question, $default = null)
{
// @codeCoverageIgnoreStart
$output->writeln($question);
$ret = trim(fgets(STDIN));
return $ret ? $ret : $default;
// @codeCoverageIgnoreEnd
}
/**
* Asks a confirmation to the user.
*
* The question will be asked until the user answer by nothing, yes, or no.
*
* @param OutputInterface $output
* @param string|array $question The question to ask
* @param Boolean $default The default answer if the user enters nothing
*
* @return Boolean true if the user has confirmed, false otherwise
*/
public function askConfirmation(OutputInterface $output, $question, $default = true)
{
// @codeCoverageIgnoreStart
$answer = 'z';
while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) {
$answer = $this->ask($output, $question);
}
if (false === $default) {
return $answer && 'y' == strtolower($answer[0]);
} else {
return !$answer || 'y' == strtolower($answer[0]);
}
// @codeCoverageIgnoreEnd
}
/**
* Asks for a value and validates the response.
*
* @param OutputInterface $output
* @param string|array $question
* @param Closure $validator
* @param integer $attempts Max number of times to ask before giving up (false by default, which means infinite)
*
* @return mixed
*
* @throws \Exception When any of the validator returns an error
*/
public function askAndValidate(OutputInterface $output, $question, \Closure $validator, $attempts = false)
{
// @codeCoverageIgnoreStart
$error = null;
while (false === $attempts || $attempts--) {
if (null !== $error) {
$output->writeln($this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error'));
}
$value = $this->ask($output, $question, null);
try {
return $validator($value);
} catch (\Exception $error) {
}
}
throw $error;
// @codeCoverageIgnoreEnd
}
/**
* Returns the helper's canonical name
*/
public function getName()
{
return 'dialog';
}
}
<?php
namespace Symfony\Component\Console;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\Output;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Command\HelpCommand;
use Symfony\Component\Console\Command\ListCommand;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Helper\FormatterHelper;
use Symfony\Component\Console\Helper\DialogHelper;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* An Application is the container for a collection of commands.
*
* It is the main entry point of a Console application.
*
* This class is optimized for a standard CLI environment.
*
* Usage:
*
* $app = new Application('myapp', '1.0 (stable)');
* $app->addCommand(new SimpleCommand());
* $app->run();
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class Application
{
protected $commands;
protected $aliases;
protected $wantHelps = false;
protected $runningCommand;
protected $name;
protected $version;
protected $catchExceptions;
protected $autoExit;
protected $definition;
protected $helperSet;
/**
* Constructor.
*
* @param string $name The name of the application
* @param string $version The version of the application
*/
public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
{
$this->name = $name;
$this->version = $version;
$this->catchExceptions = true;
$this->autoExit = true;
$this->commands = array();
$this->aliases = array();
$this->helperSet = new HelperSet(array(
new FormatterHelper(),
new DialogHelper(),
));
$this->addCommand(new HelpCommand());
$this->addCommand(new ListCommand());
$this->definition = new InputDefinition(array(
new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
new InputOption('--help', '-h', InputOption::PARAMETER_NONE, 'Display this help message.'),
new InputOption('--quiet', '-q', InputOption::PARAMETER_NONE, 'Do not output any message.'),
new InputOption('--verbose', '-v', InputOption::PARAMETER_NONE, 'Increase verbosity of messages.'),
new InputOption('--version', '-V', InputOption::PARAMETER_NONE, 'Display this program version.'),
new InputOption('--ansi', '-a', InputOption::PARAMETER_NONE, 'Force ANSI output.'),
new InputOption('--no-interaction', '-n', InputOption::PARAMETER_NONE, 'Do not ask any interactive question.'),
));
}
/**
* Runs the current application.
*
* @param InputInterface $input An Input instance
* @param OutputInterface $output An Output instance
*
* @return integer 0 if everything went fine, or an error code
*
* @throws \Exception When doRun returns Exception
*/
public function run(InputInterface $input = null, OutputInterface $output = null)
{
if (null === $input) {
$input = new ArgvInput();
}
if (null === $output) {
$output = new ConsoleOutput();
}
try {
$statusCode = $this->doRun($input, $output);
} catch (\Exception $e) {
if (!$this->catchExceptions) {
throw $e;
}
$this->renderException($e, $output);
$statusCode = $e->getCode();
$statusCode = is_numeric($statusCode) && $statusCode ? $statusCode : 1;
}
if ($this->autoExit) {
if ($statusCode > 255) {
$statusCode = 255;
}
// @codeCoverageIgnoreStart
exit($statusCode);
// @codeCoverageIgnoreEnd
} else {
return $statusCode;
}
}
/**
* Runs the current application.
*
* @param InputInterface $input An Input instance
* @param OutputInterface $output An Output instance
*
* @return integer 0 if everything went fine, or an error code
*/
public function doRun(InputInterface $input, OutputInterface $output)
{
$name = $this->getCommandName($input);
if (true === $input->hasParameterOption(array('--ansi', '-a'))) {
$output->setDecorated(true);
}
if (true === $input->hasParameterOption(array('--help', '-h'))) {
if (!$name) {
$name = 'help';
$input = new ArrayInput(array('command' => 'help'));
} else {
$this->wantHelps = true;
}
}
if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) {
$input->setInteractive(false);
}
if (true === $input->hasParameterOption(array('--quiet', '-q'))) {
$output->setVerbosity(Output::VERBOSITY_QUIET);
} elseif (true === $input->hasParameterOption(array('--verbose', '-v'))) {
$output->setVerbosity(Output::VERBOSITY_VERBOSE);
}
if (true === $input->hasParameterOption(array('--version', '-V'))) {
$output->writeln($this->getLongVersion());
return 0;
}
if (!$name) {
$name = 'list';
$input = new ArrayInput(array('command' => 'list'));
}
// the command name MUST be the first element of the input
$command = $this->findCommand($name);
$this->runningCommand = $command;
$statusCode = $command->run($input, $output);
$this->runningCommand = null;
return is_numeric($statusCode) ? $statusCode : 0;
}
/**
* Set a helper set to be used with the command.
*
* @param HelperSet $helperSet The helper set
*/
public function setHelperSet(HelperSet $helperSet)
{
$this->helperSet = $helperSet;
}
/**
* Get the helper set associated with the command
*
* @return HelperSet The HelperSet instance associated with this command
*/
public function getHelperSet()
{
return $this->helperSet;
}
/**
* Gets the InputDefinition related to this Application.
*
* @return InputDefinition The InputDefinition instance
*/
public function getDefinition()
{
return $this->definition;
}
/**
* Gets the help message.
*
* @return string A help message.
*/
public function getHelp()
{
$messages = array(
$this->getLongVersion(),
'',
'<comment>Usage:</comment>',
sprintf(" [options] command [arguments]\n"),
'<comment>Options:</comment>',
);
foreach ($this->definition->getOptions() as $option) {
$messages[] = sprintf(' %-29s %s %s',
'<info>--'.$option->getName().'</info>',
$option->getShortcut() ? '<info>-'.$option->getShortcut().'</info>' : ' ',
$option->getDescription()
);
}
return implode("\n", $messages);
}
/**
* Sets whether to catch exceptions or not during commands execution.
*
* @param Boolean $boolean Whether to catch exceptions or not during commands execution
*/
public function setCatchExceptions($boolean)
{
$this->catchExceptions = (Boolean) $boolean;
}
/**
* Sets whether to automatically exit after a command execution or not.
*
* @param Boolean $boolean Whether to automatically exit after a command execution or not
*/
public function setAutoExit($boolean)
{
$this->autoExit = (Boolean) $boolean;
}
/**
* Gets the name of the application.
*
* @return string The application name
*/
public function getName()
{
return $this->name;
}
/**
* Sets the application name.
*
* @param string $name The application name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* Gets the application version.
*
* @return string The application version
*/
public function getVersion()
{
return $this->version;
}
/**
* Sets the application version.
*
* @param string $version The application version
*/
public function setVersion($version)
{
$this->version = $version;
}
/**
* Returns the long version of the application.
*
* @return string The long application version
*/
public function getLongVersion()
{
if ('UNKNOWN' !== $this->getName() && 'UNKNOWN' !== $this->getVersion()) {
return sprintf('<info>%s</info> version <comment>%s</comment>', $this->getName(), $this->getVersion());
} else {
return '<info>Console Tool</info>';
}
}
/**
* Registers a new command.
*
* @param string $name The command name
*
* @return Command The newly created command
*/
public function register($name)
{
return $this->addCommand(new Command($name));
}
/**
* Adds an array of command objects.
*
* @param Command[] $commands An array of commands
*/
public function addCommands(array $commands)
{
foreach ($commands as $command) {
$this->addCommand($command);
}
}
/**
* Adds a command object.
*
* If a command with the same name already exists, it will be overridden.
*
* @param Command $command A Command object
*
* @return Command The registered command
*/
public function addCommand(Command $command)
{
$command->setApplication($this);
$this->commands[$command->getFullName()] = $command;
foreach ($command->getAliases() as $alias) {
$this->aliases[$alias] = $command;
}
return $command;
}
/**
* Returns a registered command by name or alias.
*
* @param string $name The command name or alias
*
* @return Command A Command object
*
* @throws \InvalidArgumentException When command name given does not exist
*/
public function getCommand($name)
{
if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) {
throw new \InvalidArgumentException(sprintf('The command "%s" does not exist.', $name));
}
$command = isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name];
if ($this->wantHelps) {
$this->wantHelps = false;
$helpCommand = $this->getCommand('help');
$helpCommand->setCommand($command);
return $helpCommand;
}
return $command;
}
/**
* Returns true if the command exists, false otherwise
*
* @param string $name The command name or alias
*
* @return Boolean true if the command exists, false otherwise
*/
public function hasCommand($name)
{
return isset($this->commands[$name]) || isset($this->aliases[$name]);
}
/**
* Returns an array of all unique namespaces used by currently registered commands.
*
* It does not returns the global namespace which always exists.
*
* @return array An array of namespaces
*/
public function getNamespaces()
{
$namespaces = array();
foreach ($this->commands as $command) {
if ($command->getNamespace()) {
$namespaces[$command->getNamespace()] = true;
}
}
return array_keys($namespaces);
}
/**
* Finds a registered namespace by a name or an abbreviation.
*
* @return string A registered namespace
*
* @throws \InvalidArgumentException When namespace is incorrect or ambiguous
*/
public function findNamespace($namespace)
{
$abbrevs = static::getAbbreviations($this->getNamespaces());
if (!isset($abbrevs[$namespace])) {
throw new \InvalidArgumentException(sprintf('There are no commands defined in the "%s" namespace.', $namespace));
}
if (count($abbrevs[$namespace]) > 1) {
throw new \InvalidArgumentException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions($abbrevs[$namespace])));
}
return $abbrevs[$namespace][0];
}
/**
* Finds a command by name or alias.
*
* Contrary to getCommand, this command tries to find the best
* match if you give it an abbreviation of a name or alias.
*
* @param string $name A command name or a command alias
*
* @return Command A Command instance
*
* @throws \InvalidArgumentException When command name is incorrect or ambiguous
*/
public function findCommand($name)
{
// namespace
$namespace = '';
if (false !== $pos = strrpos($name, ':')) {
$namespace = $this->findNamespace(substr($name, 0, $pos));
$name = substr($name, $pos + 1);
}
$fullName = $namespace ? $namespace.':'.$name : $name;
// name
$commands = array();
foreach ($this->commands as $command) {
if ($command->getNamespace() == $namespace) {
$commands[] = $command->getName();
}
}
$abbrevs = static::getAbbreviations($commands);
if (isset($abbrevs[$name]) && 1 == count($abbrevs[$name])) {
return $this->getCommand($namespace ? $namespace.':'.$abbrevs[$name][0] : $abbrevs[$name][0]);
}
if (isset($abbrevs[$name]) && count($abbrevs[$name]) > 1) {
$suggestions = $this->getAbbreviationSuggestions(array_map(function ($command) use ($namespace) { return $namespace.':'.$command; }, $abbrevs[$name]));
throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $fullName, $suggestions));
}
// aliases
$abbrevs = static::getAbbreviations(array_keys($this->aliases));
if (!isset($abbrevs[$fullName])) {
throw new \InvalidArgumentException(sprintf('Command "%s" is not defined.', $fullName));
}
if (count($abbrevs[$fullName]) > 1) {
throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $fullName, $this->getAbbreviationSuggestions($abbrevs[$fullName])));
}
return $this->getCommand($abbrevs[$fullName][0]);
}
/**
* Gets the commands (registered in the given namespace if provided).
*
* The array keys are the full names and the values the command instances.
*
* @param string $namespace A namespace name
*
* @return array An array of Command instances
*/
public function getCommands($namespace = null)
{
if (null === $namespace) {
return $this->commands;
}
$commands = array();
foreach ($this->commands as $name => $command) {
if ($namespace === $command->getNamespace()) {
$commands[$name] = $command;
}
}
return $commands;
}
/**
* Returns an array of possible abbreviations given a set of names.
*
* @param array $names An array of names
*
* @return array An array of abbreviations
*/
static public function getAbbreviations($names)
{
$abbrevs = array();
foreach ($names as $name) {
for ($len = strlen($name) - 1; $len > 0; --$len) {
$abbrev = substr($name, 0, $len);
if (!isset($abbrevs[$abbrev])) {
$abbrevs[$abbrev] = array($name);
} else {
$abbrevs[$abbrev][] = $name;
}
}
}
// Non-abbreviations always get entered, even if they aren't unique
foreach ($names as $name) {
$abbrevs[$name] = array($name);
}
return $abbrevs;
}
/**
* Returns a text representation of the Application.
*
* @param string $namespace An optional namespace name
*
* @return string A string representing the Application
*/
public function asText($namespace = null)
{
$commands = $namespace ? $this->getCommands($this->findNamespace($namespace)) : $this->commands;
$messages = array($this->getHelp(), '');
if ($namespace) {
$messages[] = sprintf("<comment>Available commands for the \"%s\" namespace:</comment>", $namespace);
} else {
$messages[] = '<comment>Available commands:</comment>';
}
$width = 0;
foreach ($commands as $command) {
$width = strlen($command->getName()) > $width ? strlen($command->getName()) : $width;
}
$width += 2;
// add commands by namespace
foreach ($this->sortCommands($commands) as $space => $commands) {
if (!$namespace && '_global' !== $space) {
$messages[] = '<comment>'.$space.'</comment>';
}
foreach ($commands as $command) {
$aliases = $command->getAliases() ? '<comment> ('.implode(', ', $command->getAliases()).')</comment>' : '';
$messages[] = sprintf(" <info>%-${width}s</info> %s%s", ($command->getNamespace() ? ':' : '').$command->getName(), $command->getDescription(), $aliases);
}
}
return implode("\n", $messages);
}
/**
* Returns an XML representation of the Application.
*
* @param string $namespace An optional namespace name
* @param Boolean $asDom Whether to return a DOM or an XML string
*
* @return string|DOMDocument An XML string representing the Application
*/
public function asXml($namespace = null, $asDom = false)
{
$commands = $namespace ? $this->getCommands($this->findNamespace($namespace)) : $this->commands;
$dom = new \DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;
$dom->appendChild($xml = $dom->createElement('symfony'));
$xml->appendChild($commandsXML = $dom->createElement('commands'));
if ($namespace) {
$commandsXML->setAttribute('namespace', $namespace);
} else {
$xml->appendChild($namespacesXML = $dom->createElement('namespaces'));
}
// add commands by namespace
foreach ($this->sortCommands($commands) as $space => $commands) {
if (!$namespace) {
$namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
$namespaceArrayXML->setAttribute('id', $space);
}
foreach ($commands as $command) {
if (!$namespace) {
$namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
$commandXML->appendChild($dom->createTextNode($command->getName()));
}
$node = $command->asXml(true)->getElementsByTagName('command')->item(0);
$node = $dom->importNode($node, true);
$commandsXML->appendChild($node);
}
}
return $asDom ? $dom : $dom->saveXml();
}
/**
* Renders a catched exception.
*
* @param Exception $e An exception instance
* @param OutputInterface $output An OutputInterface instance
*/
public function renderException($e, $output)
{
$strlen = function ($string)
{
return function_exists('mb_strlen') ? mb_strlen($string) : strlen($string);
};
$title = sprintf(' [%s] ', get_class($e));
$len = $strlen($title);
$lines = array();
foreach (explode("\n", $e->getMessage()) as $line) {
$lines[] = sprintf(' %s ', $line);
$len = max($strlen($line) + 4, $len);
}
$messages = array(str_repeat(' ', $len), $title.str_repeat(' ', $len - $strlen($title)));
foreach ($lines as $line) {
$messages[] = $line.str_repeat(' ', $len - $strlen($line));
}
$messages[] = str_repeat(' ', $len);
$output->writeln("\n");
foreach ($messages as $message) {
$output->writeln('<error>'.$message.'</error>');
}
$output->writeln("\n");
if (null !== $this->runningCommand) {
$output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())));
$output->writeln("\n");
}
if (Output::VERBOSITY_VERBOSE === $output->getVerbosity()) {
$output->writeln('</comment>Exception trace:</comment>');
// exception related properties
$trace = $e->getTrace();
array_unshift($trace, array(
'function' => '',
'file' => $e->getFile() != null ? $e->getFile() : 'n/a',
'line' => $e->getLine() != null ? $e->getLine() : 'n/a',
'args' => array(),
));
for ($i = 0, $count = count($trace); $i < $count; $i++) {
$class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
$type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
$function = $trace[$i]['function'];
$file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a';
$line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';
$output->writeln(sprintf(' %s%s%s() at <info>%s:%s</info>', $class, $type, $function, $file, $line));
}
$output->writeln("\n");
}
}
protected function getCommandName(InputInterface $input)
{
return $input->getFirstArgument('command');
}
protected function sortCommands($commands)
{
$namespacedCommands = array();
foreach ($commands as $name => $command) {
$key = $command->getNamespace() ? $command->getNamespace() : '_global';
if (!isset($namespacedCommands[$key])) {
$namespacedCommands[$key] = array();
}
$namespacedCommands[$key][$name] = $command;
}
ksort($namespacedCommands);
foreach ($namespacedCommands as $name => &$commands) {
ksort($commands);
}
return $namespacedCommands;
}
protected function getAbbreviationSuggestions($abbrevs)
{
return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : '');
}
}
<?php
namespace Symfony\Component\Console\Tester;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\StreamOutput;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class ApplicationTester
{
protected $application;
protected $display;
protected $input;
protected $output;
/**
* Constructor.
*
* @param Application $application A Application instance to test.
*/
public function __construct(Application $application)
{
$this->application = $application;
}
/**
* Executes the application.
*
* Available options:
*
* * interactive: Sets the input interactive flag
* * decorated: Sets the output decorated flag
* * verbosity: Sets the output verbosity flag
*
* @param array $input An array of arguments and options
* @param array $options An array of options
*/
public function run(array $input, $options = array())
{
$this->input = new ArrayInput($input);
if (isset($options['interactive'])) {
$this->input->setInteractive($options['interactive']);
}
$this->output = new StreamOutput(fopen('php://memory', 'w', false));
if (isset($options['decorated'])) {
$this->output->setDecorated($options['decorated']);
}
if (isset($options['verbosity'])) {
$this->output->setVerbosity($options['verbosity']);
}
$ret = $this->application->run($this->input, $this->output);
rewind($this->output->getStream());
return $this->display = stream_get_contents($this->output->getStream());
}
/**
* Gets the display returned by the last execution of the application.
*
* @return string The display
*/
public function getDisplay()
{
return $this->display;
}
/**
* Gets the input instance used by the last execution of the application.
*
* @return InputInterface The current input instance
*/
public function getInput()
{
return $this->input;
}
/**
* Gets the output instance used by the last execution of the application.
*
* @return OutputInterface The current output instance
*/
public function getOutput()
{
return $this->output;
}
}
<?php
namespace Symfony\Component\Console\Tester;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\StreamOutput;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class CommandTester
{
protected $command;
protected $display;
protected $input;
protected $output;
/**
* Constructor.
*
* @param Command $command A Command instance to test.
*/
public function __construct(Command $command)
{
$this->command = $command;
}
/**
* Executes the command.
*
* Available options:
*
* * interactive: Sets the input interactive flag
* * decorated: Sets the output decorated flag
* * verbosity: Sets the output verbosity flag
*
* @param array $input An array of arguments and options
* @param array $options An array of options
*/
public function execute(array $input, array $options = array())
{
$this->input = new ArrayInput($input);
if (isset($options['interactive'])) {
$this->input->setInteractive($options['interactive']);
}
$this->output = new StreamOutput(fopen('php://memory', 'w', false));
if (isset($options['decorated'])) {
$this->output->setDecorated($options['decorated']);
}
if (isset($options['verbosity'])) {
$this->output->setVerbosity($options['verbosity']);
}
$ret = $this->command->run($this->input, $this->output);
rewind($this->output->getStream());
return $this->display = stream_get_contents($this->output->getStream());
}
/**
* Gets the display returned by the last execution of the command.
*
* @return string The display
*/
public function getDisplay()
{
return $this->display;
}
/**
* Gets the input instance used by the last execution of the command.
*
* @return InputInterface The current input instance
*/
public function getInput()
{
return $this->input;
}
/**
* Gets the output instance used by the last execution of the command.
*
* @return OutputInterface The current output instance
*/
public function getOutput()
{
return $this->output;
}
}
<?php
namespace Symfony\Component\Console\Input;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* Input is the base class for all concrete Input classes.
*
* Three concrete classes are provided by default:
*
* * `ArgvInput`: The input comes from the CLI arguments (argv)
* * `StringInput`: The input is provided as a string
* * `ArrayInput`: The input is provided as an array
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
abstract class Input implements InputInterface
{
protected $definition;
protected $options;
protected $arguments;
protected $interactive = true;
/**
* Constructor.
*
* @param InputDefinition $definition A InputDefinition instance
*/
public function __construct(InputDefinition $definition = null)
{
if (null === $definition) {
$this->definition = new InputDefinition();
} else {
$this->bind($definition);
$this->validate();
}
}
/**
* Binds the current Input instance with the given arguments and options.
*
* @param InputDefinition $definition A InputDefinition instance
*/
public function bind(InputDefinition $definition)
{
$this->arguments = array();
$this->options = array();
$this->definition = $definition;
$this->parse();
}
/**
* Processes command line arguments.
*/
abstract protected function parse();
/**
* @throws \RuntimeException When not enough arguments are given
*/
public function validate()
{
if (count($this->arguments) < $this->definition->getArgumentRequiredCount()) {
throw new \RuntimeException('Not enough arguments.');
}
}
public function isInteractive()
{
return $this->interactive;
}
public function setInteractive($interactive)
{
$this->interactive = (Boolean) $interactive;
}
/**
* Returns the argument values.
*
* @return array An array of argument values
*/
public function getArguments()
{
return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
}
/**
* Returns the argument value for a given argument name.
*
* @param string $name The argument name
*
* @return mixed The argument value
*
* @throws \InvalidArgumentException When argument given doesn't exist
*/
public function getArgument($name)
{
if (!$this->definition->hasArgument($name)) {
throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
}
return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault();
}
/**
* Sets an argument value by name.
*
* @param string $name The argument name
* @param string $value The argument value
*
* @throws \InvalidArgumentException When argument given doesn't exist
*/
public function setArgument($name, $value)
{
if (!$this->definition->hasArgument($name)) {
throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
}
$this->arguments[$name] = $value;
}
/**
* Returns true if an InputArgument object exists by name or position.
*
* @param string|integer $name The InputArgument name or position
*
* @return Boolean true if the InputArgument object exists, false otherwise
*/
public function hasArgument($name)
{
return $this->definition->hasArgument($name);
}
/**
* Returns the options values.
*
* @return array An array of option values
*/
public function getOptions()
{
return array_merge($this->definition->getOptionDefaults(), $this->options);
}
/**
* Returns the option value for a given option name.
*
* @param string $name The option name
*
* @return mixed The option value
*
* @throws \InvalidArgumentException When option given doesn't exist
*/
public function getOption($name)
{
if (!$this->definition->hasOption($name)) {
throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
}
return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
}
/**
* Sets an option value by name.
*
* @param string $name The option name
* @param string $value The option value
*
* @throws \InvalidArgumentException When option given doesn't exist
*/
public function setOption($name, $value)
{
if (!$this->definition->hasOption($name)) {
throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
}
$this->options[$name] = $value;
}
/**
* Returns true if an InputOption object exists by name.
*
* @param string $name The InputOption name
*
* @return Boolean true if the InputOption object exists, false otherwise
*/
public function hasOption($name)
{
return $this->definition->hasOption($name);
}
}
<?php
namespace Symfony\Component\Console\Input;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* ArrayInput represents an input provided as an array.
*
* Usage:
*
* $input = new ArrayInput(array('name' => 'foo', '--bar' => 'foobar'));
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class ArrayInput extends Input
{
protected $parameters;
/**
* Constructor.
*
* @param array $param An array of parameters
* @param InputDefinition $definition A InputDefinition instance
*/
public function __construct(array $parameters, InputDefinition $definition = null)
{
$this->parameters = $parameters;
parent::__construct($definition);
}
/**
* Returns the first argument from the raw parameters (not parsed).
*
* @return string The value of the first argument or null otherwise
*/
public function getFirstArgument()
{
foreach ($this->parameters as $key => $value) {
if ($key && '-' === $key[0]) {
continue;
}
return $value;
}
}
/**
* Returns true if the raw parameters (not parsed) contains a value.
*
* This method is to be used to introspect the input parameters
* before it has been validated. It must be used carefully.
*
* @param string|array $value The values to look for in the raw parameters (can be an array)
*
* @return Boolean true if the value is contained in the raw parameters
*/
public function hasParameterOption($values)
{
if (!is_array($values)) {
$values = array($values);
}
foreach ($this->parameters as $k => $v) {
if (!is_int($k)) {
$v = $k;
}
if (in_array($v, $values)) {
return true;
}
}
return false;
}
/**
* Processes command line arguments.
*/
protected function parse()
{
foreach ($this->parameters as $key => $value) {
if ('--' === substr($key, 0, 2)) {
$this->addLongOption(substr($key, 2), $value);
} elseif ('-' === $key[0]) {
$this->addShortOption(substr($key, 1), $value);
} else {
$this->addArgument($key, $value);
}
}
}
/**
* Adds a short option value.
*
* @param string $shortcut The short option key
* @param mixed $value The value for the option
*
* @throws \RuntimeException When option given doesn't exist
*/
protected function addShortOption($shortcut, $value)
{
if (!$this->definition->hasShortcut($shortcut)) {
throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
}
$this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
}
/**
* Adds a long option value.
*
* @param string $name The long option key
* @param mixed $value The value for the option
*
* @throws \InvalidArgumentException When option given doesn't exist
* @throws \InvalidArgumentException When a required value is missing
*/
protected function addLongOption($name, $value)
{
if (!$this->definition->hasOption($name)) {
throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
}
$option = $this->definition->getOption($name);
if (null === $value) {
if ($option->isParameterRequired()) {
throw new \InvalidArgumentException(sprintf('The "--%s" option requires a value.', $name));
}
$value = $option->isParameterOptional() ? $option->getDefault() : true;
}
$this->options[$name] = $value;
}
/**
* Adds an argument value.
*
* @param string $name The argument name
* @param mixed $value The value for the argument
*
* @throws \InvalidArgumentException When argument given doesn't exist
*/
protected function addArgument($name, $value)
{
if (!$this->definition->hasArgument($name)) {
throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
}
$this->arguments[$name] = $value;
}
}
<?php
namespace Symfony\Component\Console\Input;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* Represents a command line option.
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class InputOption
{
const PARAMETER_NONE = 1;
const PARAMETER_REQUIRED = 2;
const PARAMETER_OPTIONAL = 4;
const PARAMETER_IS_ARRAY = 8;
protected $name;
protected $shortcut;
protected $mode;
protected $default;
protected $description;
/**
* Constructor.
*
* @param string $name The option name
* @param string $shortcut The shortcut (can be null)
* @param integer $mode The option mode: self::PARAMETER_REQUIRED, self::PARAMETER_NONE or self::PARAMETER_OPTIONAL
* @param string $description A description text
* @param mixed $default The default value (must be null for self::PARAMETER_REQUIRED or self::PARAMETER_NONE)
*
* @throws \InvalidArgumentException If option mode is invalid or incompatible
*/
public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null)
{
if ('--' === substr($name, 0, 2)) {
$name = substr($name, 2);
}
if (empty($shortcut)) {
$shortcut = null;
}
if (null !== $shortcut) {
if ('-' === $shortcut[0]) {
$shortcut = substr($shortcut, 1);
}
}
if (null === $mode) {
$mode = self::PARAMETER_NONE;
} else if (!is_int($mode) || $mode > 15) {
throw new \InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
}
$this->name = $name;
$this->shortcut = $shortcut;
$this->mode = $mode;
$this->description = $description;
if ($this->isArray() && !$this->acceptParameter()) {
throw new \InvalidArgumentException('Impossible to have an option mode PARAMETER_IS_ARRAY if the option does not accept a parameter.');
}
$this->setDefault($default);
}
/**
* Returns the shortcut.
*
* @return string The shortcut
*/
public function getShortcut()
{
return $this->shortcut;
}
/**
* Returns the name.
*
* @return string The name
*/
public function getName()
{
return $this->name;
}
/**
* Returns true if the option accept a parameter.
*
* @return Boolean true if parameter mode is not self::PARAMETER_NONE, false otherwise
*/
public function acceptParameter()
{
return $this->isParameterRequired() || $this->isParameterOptional();
}
/**
* Returns true if the option requires a parameter.
*
* @return Boolean true if parameter mode is self::PARAMETER_REQUIRED, false otherwise
*/
public function isParameterRequired()
{
return self::PARAMETER_REQUIRED === (self::PARAMETER_REQUIRED & $this->mode);
}
/**
* Returns true if the option takes an optional parameter.
*
* @return Boolean true if parameter mode is self::PARAMETER_OPTIONAL, false otherwise
*/
public function isParameterOptional()
{
return self::PARAMETER_OPTIONAL === (self::PARAMETER_OPTIONAL & $this->mode);
}
/**
* Returns true if the option can take multiple values.
*
* @return Boolean true if mode is self::PARAMETER_IS_ARRAY, false otherwise
*/
public function isArray()
{
return self::PARAMETER_IS_ARRAY === (self::PARAMETER_IS_ARRAY & $this->mode);
}
/**
* Sets the default value.
*
* @param mixed $default The default value
*/
public function setDefault($default = null)
{
if (self::PARAMETER_NONE === (self::PARAMETER_NONE & $this->mode) && null !== $default) {
throw new \LogicException('Cannot set a default value when using Option::PARAMETER_NONE mode.');
}
if ($this->isArray()) {
if (null === $default) {
$default = array();
} elseif (!is_array($default)) {
throw new \LogicException('A default value for an array option must be an array.');
}
}
$this->default = $this->acceptParameter() ? $default : false;
}
/**
* Returns the default value.
*
* @return mixed The default value
*/
public function getDefault()
{
return $this->default;
}
/**
* Returns the description text.
*
* @return string The description text
*/
public function getDescription()
{
return $this->description;
}
}
<?php
namespace Symfony\Component\Console\Input;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* A InputDefinition represents a set of valid command line arguments and options.
*
* Usage:
*
* $definition = new InputDefinition(array(
* new InputArgument('name', InputArgument::REQUIRED),
* new InputOption('foo', 'f', InputOption::PARAMETER_REQUIRED),
* ));
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class InputDefinition
{
protected $arguments;
protected $requiredCount;
protected $hasAnArrayArgument = false;
protected $hasOptional;
protected $options;
protected $shortcuts;
/**
* Constructor.
*
* @param array $definition An array of InputArgument and InputOption instance
*/
public function __construct(array $definition = array())
{
$this->setDefinition($definition);
}
public function setDefinition(array $definition)
{
$arguments = array();
$options = array();
foreach ($definition as $item) {
if ($item instanceof InputOption) {
$options[] = $item;
} else {
$arguments[] = $item;
}
}
$this->setArguments($arguments);
$this->setOptions($options);
}
/**
* Sets the InputArgument objects.
*
* @param array $arguments An array of InputArgument objects
*/
public function setArguments($arguments = array())
{
$this->arguments = array();
$this->requiredCount = 0;
$this->hasOptional = false;
$this->hasAnArrayArgument = false;
$this->addArguments($arguments);
}
/**
* Add an array of InputArgument objects.
*
* @param InputArgument[] $arguments An array of InputArgument objects
*/
public function addArguments($arguments = array())
{
if (null !== $arguments) {
foreach ($arguments as $argument) {
$this->addArgument($argument);
}
}
}
/**
* Add an InputArgument object.
*
* @param InputArgument $argument An InputArgument object
*
* @throws \LogicException When incorrect argument is given
*/
public function addArgument(InputArgument $argument)
{
if (isset($this->arguments[$argument->getName()])) {
throw new \LogicException(sprintf('An argument with name "%s" already exist.', $argument->getName()));
}
if ($this->hasAnArrayArgument) {
throw new \LogicException('Cannot add an argument after an array argument.');
}
if ($argument->isRequired() && $this->hasOptional) {
throw new \LogicException('Cannot add a required argument after an optional one.');
}
if ($argument->isArray()) {
$this->hasAnArrayArgument = true;
}
if ($argument->isRequired()) {
++$this->requiredCount;
} else {
$this->hasOptional = true;
}
$this->arguments[$argument->getName()] = $argument;
}
/**
* Returns an InputArgument by name or by position.
*
* @param string|integer $name The InputArgument name or position
*
* @return InputArgument An InputArgument object
*
* @throws \InvalidArgumentException When argument given doesn't exist
*/
public function getArgument($name)
{
$arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
if (!$this->hasArgument($name)) {
throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
}
return $arguments[$name];
}
/**
* Returns true if an InputArgument object exists by name or position.
*
* @param string|integer $name The InputArgument name or position
*
* @return Boolean true if the InputArgument object exists, false otherwise
*/
public function hasArgument($name)
{
$arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
return isset($arguments[$name]);
}
/**
* Gets the array of InputArgument objects.
*
* @return array An array of InputArgument objects
*/
public function getArguments()
{
return $this->arguments;
}
/**
* Returns the number of InputArguments.
*
* @return integer The number of InputArguments
*/
public function getArgumentCount()
{
return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments);
}
/**
* Returns the number of required InputArguments.
*
* @return integer The number of required InputArguments
*/
public function getArgumentRequiredCount()
{
return $this->requiredCount;
}
/**
* Gets the default values.
*
* @return array An array of default values
*/
public function getArgumentDefaults()
{
$values = array();
foreach ($this->arguments as $argument) {
$values[$argument->getName()] = $argument->getDefault();
}
return $values;
}
/**
* Sets the InputOption objects.
*
* @param array $options An array of InputOption objects
*/
public function setOptions($options = array())
{
$this->options = array();
$this->shortcuts = array();
$this->addOptions($options);
}
/**
* Add an array of InputOption objects.
*
* @param InputOption[] $options An array of InputOption objects
*/
public function addOptions($options = array())
{
foreach ($options as $option) {
$this->addOption($option);
}
}
/**
* Add an InputOption object.
*
* @param InputOption $option An InputOption object
*
* @throws \LogicException When option given already exist
*/
public function addOption(InputOption $option)
{
if (isset($this->options[$option->getName()])) {
throw new \LogicException(sprintf('An option named "%s" already exist.', $option->getName()));
} else if (isset($this->shortcuts[$option->getShortcut()])) {
throw new \LogicException(sprintf('An option with shortcut "%s" already exist.', $option->getShortcut()));
}
$this->options[$option->getName()] = $option;
if ($option->getShortcut()) {
$this->shortcuts[$option->getShortcut()] = $option->getName();
}
}
/**
* Returns an InputOption by name.
*
* @param string $name The InputOption name
*
* @return InputOption A InputOption object
*/
public function getOption($name)
{
if (!$this->hasOption($name)) {
throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
}
return $this->options[$name];
}
/**
* Returns true if an InputOption object exists by name.
*
* @param string $name The InputOption name
*
* @return Boolean true if the InputOption object exists, false otherwise
*/
public function hasOption($name)
{
return isset($this->options[$name]);
}
/**
* Gets the array of InputOption objects.
*
* @return array An array of InputOption objects
*/
public function getOptions()
{
return $this->options;
}
/**
* Returns true if an InputOption object exists by shortcut.
*
* @param string $name The InputOption shortcut
*
* @return Boolean true if the InputOption object exists, false otherwise
*/
public function hasShortcut($name)
{
return isset($this->shortcuts[$name]);
}
/**
* Gets an InputOption by shortcut.
*
* @return InputOption An InputOption object
*/
public function getOptionForShortcut($shortcut)
{
return $this->getOption($this->shortcutToName($shortcut));
}
/**
* Gets an array of default values.
*
* @return array An array of all default values
*/
public function getOptionDefaults()
{
$values = array();
foreach ($this->options as $option) {
$values[$option->getName()] = $option->getDefault();
}
return $values;
}
/**
* Returns the InputOption name given a shortcut.
*
* @param string $shortcut The shortcut
*
* @return string The InputOption name
*
* @throws \InvalidArgumentException When option given does not exist
*/
protected function shortcutToName($shortcut)
{
if (!isset($this->shortcuts[$shortcut])) {
throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
}
return $this->shortcuts[$shortcut];
}
/**
* Gets the synopsis.
*
* @return string The synopsis
*/
public function getSynopsis()
{
$elements = array();
foreach ($this->getOptions() as $option) {
$shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
$elements[] = sprintf('['.($option->isParameterRequired() ? '%s--%s="..."' : ($option->isParameterOptional() ? '%s--%s[="..."]' : '%s--%s')).']', $shortcut, $option->getName());
}
foreach ($this->getArguments() as $argument) {
$elements[] = sprintf($argument->isRequired() ? '%s' : '[%s]', $argument->getName().($argument->isArray() ? '1' : ''));
if ($argument->isArray()) {
$elements[] = sprintf('... [%sN]', $argument->getName());
}
}
return implode(' ', $elements);
}
/**
* Returns a textual representation of the InputDefinition.
*
* @return string A string representing the InputDefinition
*/
public function asText()
{
// find the largest option or argument name
$max = 0;
foreach ($this->getOptions() as $option) {
$max = strlen($option->getName()) + 2 > $max ? strlen($option->getName()) + 2 : $max;
}
foreach ($this->getArguments() as $argument) {
$max = strlen($argument->getName()) > $max ? strlen($argument->getName()) : $max;
}
++$max;
$text = array();
if ($this->getArguments()) {
$text[] = '<comment>Arguments:</comment>';
foreach ($this->getArguments() as $argument) {
if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) {
$default = sprintf('<comment> (default: %s)</comment>', is_array($argument->getDefault()) ? str_replace("\n", '', var_export($argument->getDefault(), true)): $argument->getDefault());
} else {
$default = '';
}
$text[] = sprintf(" <info>%-${max}s</info> %s%s", $argument->getName(), $argument->getDescription(), $default);
}
$text[] = '';
}
if ($this->getOptions()) {
$text[] = '<comment>Options:</comment>';
foreach ($this->getOptions() as $option) {
if ($option->acceptParameter() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) {
$default = sprintf('<comment> (default: %s)</comment>', is_array($option->getDefault()) ? str_replace("\n", '', print_r($option->getDefault(), true)): $option->getDefault());
} else {
$default = '';
}
$multiple = $option->isArray() ? '<comment> (multiple values allowed)</comment>' : '';
$text[] = sprintf(' %-'.$max.'s %s%s%s%s', '<info>--'.$option->getName().'</info>', $option->getShortcut() ? sprintf('(-%s) ', $option->getShortcut()) : '', $option->getDescription(), $default, $multiple);
}
$text[] = '';
}
return implode("\n", $text);
}
/**
* Returns an XML representation of the InputDefinition.
*
* @param Boolean $asDom Whether to return a DOM or an XML string
*
* @return string|DOMDocument An XML string representing the InputDefinition
*/
public function asXml($asDom = false)
{
$dom = new \DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;
$dom->appendChild($definitionXML = $dom->createElement('definition'));
$definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
foreach ($this->getArguments() as $argument) {
$argumentsXML->appendChild($argumentXML = $dom->createElement('argument'));
$argumentXML->setAttribute('name', $argument->getName());
$argumentXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
$argumentXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
$argumentXML->appendChild($descriptionXML = $dom->createElement('description'));
$descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
$argumentXML->appendChild($defaultsXML = $dom->createElement('defaults'));
$defaults = is_array($argument->getDefault()) ? $argument->getDefault() : ($argument->getDefault() ? array($argument->getDefault()) : array());
foreach ($defaults as $default) {
$defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
$defaultXML->appendChild($dom->createTextNode($default));
}
}
$definitionXML->appendChild($optionsXML = $dom->createElement('options'));
foreach ($this->getOptions() as $option) {
$optionsXML->appendChild($optionXML = $dom->createElement('option'));
$optionXML->setAttribute('name', '--'.$option->getName());
$optionXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
$optionXML->setAttribute('accept_parameter', $option->acceptParameter() ? 1 : 0);
$optionXML->setAttribute('is_parameter_required', $option->isParameterRequired() ? 1 : 0);
$optionXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
$optionXML->appendChild($descriptionXML = $dom->createElement('description'));
$descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
if ($option->acceptParameter()) {
$optionXML->appendChild($defaultsXML = $dom->createElement('defaults'));
$defaults = is_array($option->getDefault()) ? $option->getDefault() : ($option->getDefault() ? array($option->getDefault()) : array());
foreach ($defaults as $default) {
$defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
$defaultXML->appendChild($dom->createTextNode($default));
}
}
}
return $asDom ? $dom : $dom->saveXml();
}
}
<?php
namespace Symfony\Component\Console\Input;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* InputInterface is the interface implemented by all input classes.
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
interface InputInterface
{
/**
* Returns the first argument from the raw parameters (not parsed).
*
* @return string The value of the first argument or null otherwise
*/
function getFirstArgument();
/**
* Returns true if the raw parameters (not parsed) contains a value.
*
* This method is to be used to introspect the input parameters
* before it has been validated. It must be used carefully.
*
* @param string $value The value to look for in the raw parameters
*
* @return Boolean true if the value is contained in the raw parameters
*/
function hasParameterOption($value);
/**
* Binds the current Input instance with the given arguments and options.
*
* @param InputDefinition $definition A InputDefinition instance
*/
function bind(InputDefinition $definition);
function validate();
function getArguments();
function getArgument($name);
function getOptions();
function getOption($name);
}
<?php
namespace Symfony\Component\Console\Input;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* ArgvInput represents an input coming from the CLI arguments.
*
* Usage:
*
* $input = new ArgvInput();
*
* By default, the `$_SERVER['argv']` array is used for the input values.
*
* This can be overridden by explicitly passing the input values in the constructor:
*
* $input = new ArgvInput($_SERVER['argv']);
*
* If you pass it yourself, don't forget that the first element of the array
* is the name of the running program.
*
* When passing an argument to the constructor, be sure that it respects
* the same rules as the argv one. It's almost always better to use the
* `StringInput` when you want to provide your own input.
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*
* @see http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html
* @see http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02
*/
class ArgvInput extends Input
{
protected $tokens;
protected $parsed;
/**
* Constructor.
*
* @param array $argv An array of parameters from the CLI (in the argv format)
* @param InputDefinition $definition A InputDefinition instance
*/
public function __construct(array $argv = null, InputDefinition $definition = null)
{
if (null === $argv) {
$argv = $_SERVER['argv'];
}
// strip the program name
array_shift($argv);
$this->tokens = $argv;
parent::__construct($definition);
}
/**
* Processes command line arguments.
*/
protected function parse()
{
$this->parsed = $this->tokens;
while (null !== $token = array_shift($this->parsed)) {
if ('--' === substr($token, 0, 2)) {
$this->parseLongOption($token);
} elseif ('-' === $token[0]) {
$this->parseShortOption($token);
} else {
$this->parseArgument($token);
}
}
}
/**
* Parses a short option.
*
* @param string $token The current token.
*/
protected function parseShortOption($token)
{
$name = substr($token, 1);
if (strlen($name) > 1) {
if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptParameter()) {
// an option with a value (with no space)
$this->addShortOption($name[0], substr($name, 1));
} else {
$this->parseShortOptionSet($name);
}
} else {
$this->addShortOption($name, null);
}
}
/**
* Parses a short option set.
*
* @param string $token The current token
*
* @throws \RuntimeException When option given doesn't exist
*/
protected function parseShortOptionSet($name)
{
$len = strlen($name);
for ($i = 0; $i < $len; $i++) {
if (!$this->definition->hasShortcut($name[$i])) {
throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i]));
}
$option = $this->definition->getOptionForShortcut($name[$i]);
if ($option->acceptParameter()) {
$this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));
break;
} else {
$this->addLongOption($option->getName(), true);
}
}
}
/**
* Parses a long option.
*
* @param string $token The current token
*/
protected function parseLongOption($token)
{
$name = substr($token, 2);
if (false !== $pos = strpos($name, '=')) {
$this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1));
} else {
$this->addLongOption($name, null);
}
}
/**
* Parses an argument.
*
* @param string $token The current token
*
* @throws \RuntimeException When too many arguments are given
*/
protected function parseArgument($token)
{
if (!$this->definition->hasArgument(count($this->arguments))) {
throw new \RuntimeException('Too many arguments.');
}
$this->arguments[$this->definition->getArgument(count($this->arguments))->getName()] = $token;
}
/**
* Adds a short option value.
*
* @param string $shortcut The short option key
* @param mixed $value The value for the option
*
* @throws \RuntimeException When option given doesn't exist
*/
protected function addShortOption($shortcut, $value)
{
if (!$this->definition->hasShortcut($shortcut)) {
throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
}
$this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
}
/**
* Adds a long option value.
*
* @param string $name The long option key
* @param mixed $value The value for the option
*
* @throws \RuntimeException When option given doesn't exist
*/
protected function addLongOption($name, $value)
{
if (!$this->definition->hasOption($name)) {
throw new \RuntimeException(sprintf('The "--%s" option does not exist.', $name));
}
$option = $this->definition->getOption($name);
if (null === $value && $option->acceptParameter()) {
// if option accepts an optional or mandatory argument
// let's see if there is one provided
$next = array_shift($this->parsed);
if ('-' !== $next[0]) {
$value = $next;
} else {
array_unshift($this->parsed, $next);
}
}
if (null === $value) {
if ($option->isParameterRequired()) {
throw new \RuntimeException(sprintf('The "--%s" option requires a value.', $name));
}
$value = $option->isParameterOptional() ? $option->getDefault() : true;
}
$this->options[$name] = $value;
}
/**
* Returns the first argument from the raw parameters (not parsed).
*
* @return string The value of the first argument or null otherwise
*/
public function getFirstArgument()
{
foreach ($this->tokens as $token) {
if ($token && '-' === $token[0]) {
continue;
}
return $token;
}
}
/**
* Returns true if the raw parameters (not parsed) contains a value.
*
* This method is to be used to introspect the input parameters
* before it has been validated. It must be used carefully.
*
* @param string|array $values The value(s) to look for in the raw parameters (can be an array)
*
* @return Boolean true if the value is contained in the raw parameters
*/
public function hasParameterOption($values)
{
if (!is_array($values)) {
$values = array($values);
}
foreach ($this->tokens as $v) {
if (in_array($v, $values)) {
return true;
}
}
return false;
}
}
<?php
namespace Symfony\Component\Console\Input;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* StringInput represents an input provided as a string.
*
* Usage:
*
* $input = new StringInput('foo --bar="foobar"');
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class StringInput extends ArgvInput
{
const REGEX_STRING = '([^ ]+?)(?: |(?<!\\\\)"|(?<!\\\\)\'|$)';
const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';
/**
* Constructor.
*
* @param string $input An array of parameters from the CLI (in the argv format)
* @param InputDefinition $definition A InputDefinition instance
*/
public function __construct($input, InputDefinition $definition = null)
{
parent::__construct(array(), $definition);
$this->tokens = $this->tokenize($input);
}
/**
* @throws \InvalidArgumentException When unable to parse input (should never happen)
*/
protected function tokenize($input)
{
$input = preg_replace('/(\r\n|\r|\n|\t)/', ' ', $input);
$tokens = array();
$length = strlen($input);
$cursor = 0;
while ($cursor < $length) {
if (preg_match('/\s+/A', $input, $match, null, $cursor)) {
} elseif (preg_match('/([^="\' ]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) {
$tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, strlen($match[3]) - 2)));
} elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) {
$tokens[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2));
} elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) {
$tokens[] = stripcslashes($match[1]);
} else {
// should never happen
// @codeCoverageIgnoreStart
throw new \InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10)));
// @codeCoverageIgnoreEnd
}
$cursor += strlen($match[0]);
}
return $tokens;
}
}
<?php
namespace Symfony\Component\Console\Input;
/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
/**
* Represents a command line argument.
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class InputArgument
{
const REQUIRED = 1;
const OPTIONAL = 2;
const IS_ARRAY = 4;
protected $name;
protected $mode;
protected $default;
protected $description;
/**
* Constructor.
*
* @param string $name The argument name
* @param integer $mode The argument mode: self::REQUIRED or self::OPTIONAL
* @param string $description A description text
* @param mixed $default The default value (for self::OPTIONAL mode only)
*
* @throws \InvalidArgumentException When argument mode is not valid
*/
public function __construct($name, $mode = null, $description = '', $default = null)
{
if (null === $mode) {
$mode = self::OPTIONAL;
} else if (is_string($mode) || $mode > 7) {
throw new \InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode));
}
$this->name = $name;
$this->mode = $mode;
$this->description = $description;
$this->setDefault($default);
}
/**
* Returns the argument name.
*
* @return string The argument name
*/
public function getName()
{
return $this->name;
}
/**
* Returns true if the argument is required.
*
* @return Boolean true if parameter mode is self::REQUIRED, false otherwise
*/
public function isRequired()
{
return self::REQUIRED === (self::REQUIRED & $this->mode);
}
/**
* Returns true if the argument can take multiple values.
*
* @return Boolean true if mode is self::IS_ARRAY, false otherwise
*/
public function isArray()
{
return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
}
/**
* Sets the default value.
*
* @param mixed $default The default value
*
* @throws \LogicException When incorrect default value is given
*/
public function setDefault($default = null)
{
if (self::REQUIRED === $this->mode && null !== $default) {
throw new \LogicException('Cannot set a default value except for Parameter::OPTIONAL mode.');
}
if ($this->isArray()) {
if (null === $default) {
$default = array();
} else if (!is_array($default)) {
throw new \LogicException('A default value for an array argument must be an array.');
}
}
$this->default = $default;
}
/**
* Returns the default value.
*
* @return mixed The default value
*/
public function getDefault()
{
return $this->default;
}
/**
* Returns the description text.
*
* @return string The description text
*/
public function getDescription()
{
return $this->description;
}
}
<EFBFBD>es<EFBFBD>yep<EFBFBD>C <0C><70><)<29>GBMB